Как использовать LINQ для сравнения одного значения с его предыдущим значением?

1

Имеет следующий код:

        Dictionary<int, List<int>> dic = new Dictionary<int, List<int>>();
        dic.Add(1, new List<int>());
        dic[1].Add(10);
        dic[1].Add(6);
        dic.Add(2, new List<int>());
        dic[2].Add(9);
        dic[2].Add(7);
        dic[2].Add(7);
        dic.Add(3, new List<int>());
        dic[3].Add(9);
        dic[3].Add(10);
        dic[3].Add(9);
        dic.Add(4, new List<int>());
        dic[4].Add(6);

        // Will give KVPs of Key 1 and 4
        var under7 = dic.Where(T => T.Value.Any(Y => Y < 7));

Поэтому я легко нашел, какие KVP содержат значение менее 7.

Мой вопрос в том, как я могу перебирать словарь, чтобы узнать KVP, которые имеют повторяющиеся значения с ключом, следующим за другим ключом (уже по порядку).

Как и в этом, нужно подобрать:

        dic.Add(2, new List<int>());
        dic[2].Add(9);
        dic[2].Add(7); // MATCH
        dic[2].Add(7); // MATCH

Но не это:

        dic.Add(3, new List<int>());
        dic[3].Add(9); // NOT MATCH
        dic[3].Add(10);
        dic[3].Add(9); // NOT MATCH

Есть ли способ сделать это с помощью LINQ?

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

        // Should give KVP of Key 2 but not 3
        var dupVals = dic.Where(T => T.Value.Aggregate( (i1, i2) => i1 == i2));
        var dupVals = dic.Where(T => T.Value.Any( (i1,i2) => i1 == i2  ));

EDIT: Итак, у Сергея был ответ:

            var result = dic.Where(kvp =>
            kvp.Value.Skip(1).Zip(kvp.Value, (x, y) => x == y).Any(b => b));

Но как именно это работает?

  • 0
    Хм ... когда вы запускаете его, он не вызывает исключение за пределами третьей строки ( dic[1].Add(10); )?
  • 3
    Я бы начал с простой задачи - проверки наличия в списке двух последовательных повторяющихся значений. Не усложняйте вопрос со словарем
Показать ещё 2 комментария
Теги:
linq
list

1 ответ

6

Вы можете проверить, имеет ли список два последовательных дубликата с

list.Skip(1).Zip(list, (x,y) => x == y).Any(b => b)

Сделайте это для каждого значения в словаре:

// yep, you can use this pretty initializer
var dic = new Dictionary<int, List<int>> {
    { 1, new List<int> { 10, 6 }},
    { 2, new List<int> { 9, 7, 7 }},
    { 3, new List<int> { 9, 10, 9 }},
    { 4, new List<int> { 6 }}
};

var result = dic.Where(kvp =>
       kvp.Value.Skip(1).Zip(kvp.Value, (x, y) => x == y).Any(b => b));

Объяснение: Расширение Enumerable.Zip применяет указанную функцию (x,y) => x == y к соответствующим элементам из двух последовательностей. Эти две последовательности - это список, а тот же список сдвинут на один элемент вперед. Т.е. вы применяете функцию для index и index + 1 элемент одного и того же списка. Эта функция дает результат сравнения элементов. Таким образом, Zip вернет последовательность значений true и false зависимости от равенства последовательных элементов. Если в результате есть какой-либо true результат, у вас есть два последовательных дубликата.

Шаг за шагом: рассмотрите следующий список 9, 10, 9, 7, 7. Если вы пропустите первый элемент в этом списке, вы получите последовательность 10, 9, 7, 7. Замедление этих двух последовательностей приведет к появлению следующих пар элементов (вы должны пометить соответствующие элементы - первый и первый, второй и второй и т.д.): (10, 9), (9, 10), (7,9), (7,7). Следующий шаг применяется к каждой паре (x,y) => x == y. Результат будет false, false, false, true. Как вы можете видеть, последняя пара (четвертый элемент из первой последовательности и четвертый элемент из второй последовательности) имеет равные элементы, поэтому она производит true. И последнее - проверять, действительно ли какая-либо из пар создала true.

  • 5
    Метод расширения Zip является одним из наиболее часто используемых методов расширения семейства Linq. Таким образом, небольшое объяснение будет иметь большое значение для будущих посетителей. В противном случае это отличный ответ.
  • 1
    +1 вы можете позвонить любому без аргумента в этом случае
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню