代码之家  ›  专栏  ›  技术社区  ›  ng5000

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

  •  -3
  • ng5000  · 技术社区  · 15 年前

    我把一个演示文稿放在一起展示一些我认为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 回复  |  直到 15 年前
        1
  •  3
  •   GManNickG    15 年前

    我会为你这样做的,但这绝对是一个糟糕的“问题”。这更多的是一个工作请求,这就是为什么我的答案是社区维基。这里没有问题要回答。

    #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,然后对匹配的自行车进行线性搜索。

        2
  •  2
  •   Evan Teran    15 年前

    我不想编辑另一个答案,因为它似乎足够理智,但有一些小事情我会做不同的。所以这里有一个稍微经过编辑的版本的另一个答案,它试图让更多的代码重用。另外,我觉得使用堆分配的对象对原始的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;
            }
        };
    }