LINQ查询以将一个对象的两个值与一个列表进行比较,其中两个对象必须匹配

时间:2018-08-24 16:12:54

标签: c# linq

我有清单,如果有帐单,还有汽车清单。每辆汽车都有两个标识符,它们分别位于账单列表中的各个列中(car_init和car_nbr)。我需要选择汽车标识符(首字母和数字都匹配)的账单。

例如,如果我有car_a(car_init:ABC,car_nbr:123)和car_b(car_init:DEF,car_nbr:456)-我需要创建所有与car_a和car_b匹配的账单清单。

帐单列表可以有超过7万行,因此,我试图找到一种不对每个查询都遍历整个列表的方法-因为用户一次即可搜索多达200辆汽车。

这是我目前所拥有的,而没有得到想要的结果。当前返回0条结果。

bills = bills
    .Where(w => request.CARS
        .Any(car => w.CarInit == car.CarInit && w.CarNbr == car.CarNbr))
    .ToList();

1 个答案:

答案 0 :(得分:2)

这是一个使用BinarySearch的解决方案(进行O(log n)比较,其中n是数组中元素的数量),我首先在car_init上对钞票和小汽车进行排序,然后对car_nbr进行排序。因为它们都已排序,所以我们知道可以随着搜索的开始一起移动索引,这使得搜索速度更快。

对于最多17个比较中的7万张钞票,我们找到了享受的元素!

using System.Collections.Generic;

namespace ConsoleApp1
{


    class Program
    {

        static void Main(string[] args)
        {
            List<Numbers> bills = new List<Numbers>();
            List<Numbers> cars = new List<Numbers>();

            bills.Add(new Bill("ABC", "123"));
            bills.Add(new Bill("ABC", "654"));
            bills.Add(new Bill("WER", "123"));
            bills.Add(new Bill("ABC", "375"));
            bills.Add(new Bill("ABC", "762"));
            bills.Add(new Bill("WER", "792"));
            bills.Add(new Bill("DDR", "123"));
            bills.Add(new Bill("DEF", "123"));
            bills.Add(new Bill("DEF", "045"));
            bills.Add(new Bill("OLY", "123"));
            bills.Add(new Bill("ABC", "342"));
            bills.Add(new Bill("QWE", "874"));
            bills.Add(new Bill("ABC", "986"));
            bills.Add(new Bill("OLY", "123"));
            bills.Add(new Bill("QWE", "123"));
            bills.Add(new Bill("QWE", "143"));

            CarBillComparer cb = new CarBillComparer();

            cars.Add(new Car("ABC", "375"));
            cars.Add(new Car("QWE", "874"));
            cars.Add(new Car("ABC", "762"));

            bills.Sort(cb);
            cars.Sort(cb);

            List<Numbers> returnBills = new List<Numbers>();

            int index = 0;

            foreach (Car onecar in cars)
            {
                int count = bills.Count - index;
                index = bills.BinarySearch(index, count, onecar, cb);
                if (index > -1)
                {
                    //Item found
                    returnBills.Add(bills[index]);
                }
                else
                {
                    index = ~index;
                }
            }

        }
        public class CarBillComparer : IComparer<Numbers>
        {
            public int Compare(Numbers x, Numbers y)
            {
                int compResult = x.car_init.CompareTo(y.car_init);
                if (compResult == 0)
                {
                    compResult = x.car_nbr.CompareTo(y.car_nbr);
                }
                return compResult;
            }
        }

        public interface Numbers
        {
            string car_init { get; }
            string car_nbr { get; }
        }

        public class Bill:Numbers
        {
            public Bill(string car_init, string car_nbr)
            {
                this.car_init = car_init;
                this.car_nbr = car_nbr;
            }

            public string car_init { get; }
            public string car_nbr { get; }
        }

        public class Car : Numbers
        {
            public Car(string car_init, string car_nbr)
            {
                this.car_init = car_init;
                this.car_nbr = car_nbr;
            }

            public string car_init { get; }
            public string car_nbr { get; }
        }


    }
}