Использование лямбда-выражений для получения подмножества, в котором элементы массива равны - PullRequest
5 голосов
/ 15 февраля 2009

У меня есть интересная проблема, и я не могу понять лямбда-выражение, чтобы сделать эту работу.

У меня есть следующий код:

List<string[]> list = GetSomeData(); // Returns large number of string[]'s
List<string[]> list2 = GetSomeData2(); // similar data, but smaller subset
&nbsp;
List<string[]> newList = list.FindAll(predicate(string[] line){ 
    return (???);
});

Я хочу вернуть только те записи в списке, в которых элемент 0 каждой строки [] равен одному из элементов 0 в списке list2.

список содержит такие данные:

"000", "Data", "more data", "etc..."

list2 содержит такие данные:

"000", "different data", "even more different data"

По сути, я мог бы написать этот код так:

List<string[]> newList = new List<string[]>();
foreach(var e in list)
{
    foreach(var e2 in list2)
    {
        if (e[0] == e2[0])
            newList.Add(e);
    }
}
return newList;

Но я пытаюсь использовать дженерики и многое другое, поэтому я ищу хорошее чистое решение. Это меня расстраивает, хотя ... может быть, находка внутри находки?

EDIT: Ответ Марка, приведенный ниже, побуждает меня экспериментировать с извращением, которое выглядит следующим образом:

var z = list.Where(x => list2.Select(y => y[0]).Contains(x[0])).ToList();

Я не уверен, насколько это эффективно, но это работает и достаточно кратко. У кого-нибудь еще есть предложения?

Ответы [ 3 ]

11 голосов
/ 15 февраля 2009

Вы могли бы присоединиться? Я бы сам использовал два шага:

var keys = new HashSet<string>(list2.Select(x => x[0]));
var data = list.Where(x => keys.Contains(x[0]));

Если у вас есть только .NET 2.0, то либо установите LINQBridge и используйте вышеуказанное (или аналогично Dictionary<>, если LINQBridge не включает HashSet<>), либо, возможно, используйте вложенный Find:

var data = list.FindAll(arr => list2.Find(arr2 => arr2[0] == arr[0]) != null);

отметим, однако, что подход Find равен O (n * m), где-как подход HashSet<> равен O (n + m) ...

3 голосов
/ 15 февраля 2009

Вы можете использовать метод расширения Intersect в System.Linq, но вам потребуется предоставить IEqualityComparer для выполнения этой работы.

    static void Main(string[] args)
    {
        List<string[]> data1 = new List<string[]>();
        List<string[]> data2 = new List<string[]>();

        var result = data1.Intersect(data2, new Comparer());
    }

    class Comparer : IEqualityComparer<string[]>
    {
        #region IEqualityComparer<string[]> Members

        bool IEqualityComparer<string[]>.Equals(string[] x, string[] y)
        {
            return x[0] == y[0];
        }

        int IEqualityComparer<string[]>.GetHashCode(string[] obj)
        {
            return obj.GetHashCode();
        }

        #endregion
    }
0 голосов
/ 24 июля 2012

Пересечение может работать на вас. Пересечь находит все элементы, которые находятся в обоих списках. Хорошо, перечитайте вопрос. Intersect не принимает заказ во внимание. Я написал немного более сложное выражение linq, которое будет возвращать список элементов, которые находятся в той же позиции (индекс) с тем же значением.

List<String> list1 = new List<String>() {"000","33", "22", "11", "111"};
List<String> list2 = new List<String>() {"000", "22", "33", "11"};

List<String> subList = list1.Select ((value, index) => new { Value = value, Index = index})
             .Where(w => list2.Skip(w.Index).FirstOrDefault() == w.Value )
             .Select (s => s.Value).ToList();


Result: {"000", "11"}

Объяснение запроса:

Выберите набор значений и позицию этого значения.

Фильтр, который устанавливает, где элемент в той же позиции во втором списке имеет одинаковое значение.

Выберите только значение (а не индекс).

Обратите внимание, я использовал: list2.Skip(w.Index).FirstOrDefault() //instead of list2[w.Index] Так что он будет обрабатывать списки разной длины.

Если вы знаете, что списки будут одинаковой длины, или list1 всегда будет короче, тогда list2[w.Index] будет, вероятно, немного быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...