帮助 - 请将此LINQ示例转换为C ++

时间:2009-07-06 09:44:35

标签: c# c++ linq

我正在整理一个演示文稿,以展示我认为C#可能比C ++提供的一些生产力提升。我在C#中编写了一些代码,我想将其转换为C ++。我没有时间或最新的C ++来做转换公正,因此在这里张贴。

要转换的代码:

using System.Collections.Generic;
using System.Drawing;
using System.Linq;

namespace LinqTest
{
    public class Vehicle
    {
        public int Id { get; set; }
        public Color Colour { get; set; }
    }

    public class Tyre
    {
        public int Id { get; set; }
        public int BikeId { get; set; }
        public int Size { get; set; }
        public string Brand { get; set; }
    }

    public class Car : Vehicle {}

    public class Bike : Vehicle {}

    public class Example
    {
        private readonly IList<Car> cars;
        private readonly IList<Tyre> bikeTyres;
        private readonly IList<Bike> bikes;

        public Example()
        {
            cars = new List<Car>
                       {
                           new Car {Id = 0, Colour = Color.Red},
                           new Car {Id = 1, Colour = Color.Blue},
                           new Car {Id = 2, Colour = Color.Green},
                           new Car {Id = 3, Colour = Color.Green}
                       };

            bikeTyres = new List<Tyre>
                            {
                                new Tyre {Id = 0, BikeId = 0, Brand = "TyreCo1", Size = 23},
                                new Tyre {Id = 1, BikeId = 0, Brand = "TyreCo1", Size = 23},
                                new Tyre {Id = 2, BikeId = 1, Brand = "TyreCo2", Size = 30},
                                new Tyre {Id = 3, BikeId = 1, Brand = "TyreCo2", Size = 30},
                                new Tyre {Id = 4, BikeId = 2, Brand = "TyreCo3", Size = 23},
                                new Tyre {Id = 5, BikeId = 2, Brand = "TyreCo3", Size = 23}
                            };

            bikes = new List<Bike>
                        {
                            new Bike {Id = 0, Colour = Color.Red},
                            new Bike {Id = 1, Colour = Color.Blue},
                            new Bike {Id = 2, Colour = Color.Green}
                        };
        }

        public IEnumerable<Vehicle> FindVehiclesByColour(Color colour)
        {
            var carVehicles = from car in cars
                           where car.Colour == colour
                           select car as Vehicle;

            var bikeVehicles = from bike in bikes
                               where bike.Colour == colour
                               select bike as Vehicle;

            return carVehicles.Union(bikeVehicles);
        }


        public IEnumerable<Bike> FindBikesByTyreSize(int size)
        {
            return (from bike in bikes
                    join tyre in bikeTyres on bike.Id equals tyre.BikeId
                    where tyre.Size == size
                    select bike).Distinct();
        }
    }
}

提前致谢。

2 个答案:

答案 0 :(得分:3)

我会为你做这件事,但对于记录来说,这绝对是一个糟糕的“问题”。这更像是一个工作请求,这就是为什么我的答案是社区维基。这里没有回答任何问题。

#include <algorithm>
#include <list>
#include <string>

namespace LinqTest
{
    // C++ does not specificy a standard GUI library.
    // This is a small hack to make the code work below.
    // In a real solution, one would probably have a real
    // Color class that stores the red, green, and blue
    // components of the colors and provides operations
    // to act upon colors.
    struct Color
    {
        static const int Red = 0;
        static const int Green = 1;
        static const int Blue = 2;

        Color(void) :
        value(0)
        {
        }

        Color(int color) :
        value(color)
        {
        }

        bool operator==(const Color& rhs) const
        {
            return value == rhs.value;
        }

        int value;
    };

    struct Vehicle
    {
        Vehicle(void) :
        Id(0)
        {
        }

        Vehicle(int id, Color colour) :
        Id(id),
        Colour(colour)
        {
        }

        bool operator==(const Vehicle& rhs) const
        {
            return Id == rhs.Id;
        }

        int Id;
        Color Colour;
    };

    struct Tyre
    {
        Tyre(void) :
        Id(0),
        BikeId(0),
        Size(0)
        {
        }

        Tyre(int id, int bikeId, int size, std::string brand) :
        Id(id),
        BikeId(bikeId),
        Size(size),
        Brand(brand)
        {
        }

        int Id;
        int BikeId;
        int Size;
        std::string Brand;
    };

    struct Car :
        public Vehicle
    {
        Car(void)
        {
        }

        Car(int id, Color colour) :
        Vehicle(id, colour)
        {
        }
    };

    struct Bike :
        public Vehicle
    {
        Bike(int id, Color colour) :
        Vehicle(id, colour)
        {
        }
    };

    class Example
    {
    // I put private up top to match yours, but most C++
    // programmers would prefer it on the bottom, justified
    // by the fact users of the class don't care or want
    // to see how the class works, they want to see how to
    // use it.
    private:
        std::list<Car> cars;
        std::list<Tyre> bikeTyres;
        std::list<Bike> bikes;

    public:
        Example(void)
        {
            cars.push_back(Car(0, Color::Red));
            cars.push_back(Car(1, Color::Blue));
            cars.push_back(Car(2, Color::Green));
            cars.push_back(Car(3, Color::Green));

            bikeTyres.push_back(Tyre(0, 0, 23, "TyreCo1"));
            bikeTyres.push_back(Tyre(1, 0, 23, "TyreCo1"));
            bikeTyres.push_back(Tyre(2, 1, 30, "TyreCo2"));
            bikeTyres.push_back(Tyre(3, 1, 30, "TyreCo2"));
            bikeTyres.push_back(Tyre(4, 2, 23, "TyreCo3"));
            bikeTyres.push_back(Tyre(5, 2, 23, "TyreCo3"));

            bikes.push_back(Bike(0, Color::Red));
            bikes.push_back(Bike(1, Color::Blue));
            bikes.push_back(Bike(2, Color::Green));
        }

        // I chose to return pointers to Vehicles to maintain any
        // polymorphic behavior, since from what I understand C#
        // would be returning references here.
        std::list<Vehicle*> FindVehiclesByColour(Color colour)
        {
            typedef std::list<Car>::iterator car_iterator;
            typedef std::list<Bike>::iterator bike_iterator;

            std::list<Vehicle*> result;

            for (car_iterator iter = cars.begin(); iter != cars.end(); ++iter)
            {
                if (iter->Colour == colour)
                {
                    result.push_back(&(*iter));
                }
            }

            for (bike_iterator iter = bikes.begin(); iter != bikes.end(); ++iter)
            {
                if (iter->Colour == colour)
                {
                    result.push_back(&(*iter));
                }
            }

            return result;
        }

        std::list<Bike*> FindBikesByTyreSize(int size)
        {
            typedef std::list<Tyre>::const_iterator tyre_iterator;
            typedef std::list<Bike>::iterator bike_iterator;

            std::list<Bike*> result;

            for (tyre_iterator tyreIter = bikeTyres.begin(); tyreIter != bikeTyres.end(); ++tyreIter)
            {
                if (tyreIter->Size == size)
                {
                    for (bike_iterator bikeIter = bikes.begin(); bikeIter != bikes.end(); ++bikeIter)
                    {
                        if (tyreIter->BikeId == bikeIter->Id)
                        {
                            result.push_back(&(*bikeIter));
                        }
                    }
                }
            }

            result.sort();
            result.unique();
            return result;
        }
    };
}

请注意,其中有一些风格内容,例如Example(void)Example()是我自己的,并不一定代表其他C ++程序员的风格。相关的,还有其他方法可以做到这一点,我的方式甚至可能不是最好的。

缺少评论,我会添加它们,但我认为它们只会妨碍,代码很简单,可以理解。

这一切都说,你显然对C ++知之甚少,所以说C#更有成效,甚至可能是真的,很难认真对待自己。此外,您在C#中执行的某些算法实际上可能效率非常低,例如只存储轮胎自行车的ID,然后对匹配的自行车进行线性搜索。

答案 1 :(得分:2)

我不想编辑其他答案,因为它看起来足够清晰,但我会做一些不同的小事情。所以这里是另一个答案的略微编辑版本,它尝试了一些代码重用。另外,我觉得使用堆分配的对象比原来的c#更加真实。

注意:公平地说,这省略了所有内存清理,但如果使用了智能指针,那就足够了。

#include <algorithm>
#include <list>
#include <string>

namespace LinqTest {

    template<typename In, typename Out, typename Pred>
    Out copy_if(In first, In last, Out res, Pred Pr) {
        while (first != last){
        if (Pr(*first))
            *res++ = *first;
        ++first;
        }
        return res;
    }

    struct ColorMatch {
        ColorMatch(Color c) : colour(c) {
        }

        bool operator()(const Vehicle *v) {
            return v->Colour == colour;
        }

    private:
        Color colour;
    };

    struct IdMatch {
        IdMatch(int id) : Id(id) {
        }

        bool operator()(const Bike *v) {
            return v->Id == Id;
        }

    private:
        int Id;
    };

    // C++ does not specificy a standard GUI library.
    // This is a small hack to make the code work below.
    // In a real solution, one would probably have a real
    // Color class that stores the red, green, and blue
    // components of the colors and provides operations
    // to act upon colors.
    struct Color {
        static const int Red = 0;
        static const int Green = 1;
        static const int Blue = 2;

        Color() : value(0) {
        }

        Color(int color) : value(color) {
        }

        bool operator==(const Color& rhs) const {
            return value == rhs.value;
        }

        int value;
    };

    struct Vehicle {
        Vehicle() : Id(0) {
        }

        Vehicle(int id, Color colour) : Id(id), Colour(colour) {
        }

        bool operator==(const Vehicle& rhs) const {
            return Id == rhs.Id;
        }

        int Id;
        Color Colour;
    };

    struct Tyre {
        Tyre() : Id(0), BikeId(0), Size(0) {
        }

        Tyre(int id, int bikeId, int size, std::string brand) : Id(id), BikeId(bikeId), Size(size), Brand(brand) {
        }

        int Id;
        int BikeId;
        int Size;
        std::string Brand;
    };

    struct Car : public Vehicle {
        Car() {
        }

        Car(int id, Color colour) : Vehicle(id, colour) {
        }
    };

    struct Bike : public Vehicle {
        Bike(int id, Color colour) : Vehicle(id, colour) {
        }
    };

    class Example {
    // I put private up top to match yours, but most C++
    // programmers would prefer it on the bottom, justified
    // by the fact users of the class don't care or want
    // to see how the class works, they want to see how to
    // use it.
    private:
        std::list<Car *> cars;
        std::list<Tyre *> bikeTyres;
        std::list<Bike *> bikes;

    public:
        Example() {
                cars.push_back(new Car(0, Color::Red));
                cars.push_back(new Car(1, Color::Blue));
                cars.push_back(new Car(2, Color::Green));
                cars.push_back(new Car(3, Color::Green));

                bikeTyres.push_back(new Tyre(0, 0, 23, "TyreCo1"));
                bikeTyres.push_back(new Tyre(1, 0, 23, "TyreCo1"));
                bikeTyres.push_back(new Tyre(2, 1, 30, "TyreCo2"));
                bikeTyres.push_back(new Tyre(3, 1, 30, "TyreCo2"));
                bikeTyres.push_back(new Tyre(4, 2, 23, "TyreCo3"));
                bikeTyres.push_back(new Tyre(5, 2, 23, "TyreCo3"));

                bikes.push_back(new Bike(0, Color::Red));
                bikes.push_back(new Bike(1, Color::Blue));
                bikes.push_back(new Bike(2, Color::Green));
        }

        // I chose to return pointers to Vehicles to maintain any
        // polymorphic behavior, since from what I understand C#
        // would be returning references here.
        std::list<Vehicle*> FindVehiclesByColour(Color colour) {
            copy_if(cars.begin(), cars.end(), std::back_inserter(result), ColorMatch(colour));
            copy_if(bikes.begin(), bikes.end(), std::back_inserter(result), ColorMatch(colour));
            return result;
        }

        std::list<Bike*> FindBikesByTyreSize(int size) {
            typedef std::list<Tyre>::const_iterator tyre_iterator;

            std::list<Bike*> result;

            for (tyre_iterator tyreIter = bikeTyres.begin(); tyreIter != bikeTyres.end(); ++tyreIter) {
                if (tyreIter->Size == size) {
                    copy_if(bikes.begin(), bikes.end(), std::back_inserter(result), IdMatch(bikeIter->Id));
                }
            }

            result.sort();
            result.unique();
            return result;
        }
    };
}