2010-07-13 3 views
1

Скажем, у меня есть следующие строки списка:Linq запрос необходимой помощи - Определение точных Поднаборы

string[] list1 = { "one", "two", "three", "four"}; 
string[] list2 = { "one", "two", "three" }; 
string[] list3 = { "three", "two", "one" }; 

Мне нужен запрос, который позволяет мне сравнивать List2 к LIST1 и возвращает истину, если все строки в list2 существуют в list1 , в том же порядке, что и список2.

Итак, такой запрос вернет true, если я сравню list2 с list1, потому что все строки в списке2 находятся в списке1, в том же порядке, что и list2.

Запрос возвращает false, если я сравниваю list3 с list1, потому что хотя строки в списке3 существуют в списке1, они не в одном порядке.

Возможно ли такой запрос?

+0

if 'string [] list1 = {" one "," two "," four "," three "};' будет сравнивать (list1, list2) по-прежнему? (технически соответствует формулировке вашего описания) –

ответ

4

Если я понимаю, что вы описываете, это должно сделать это:

list1.Intersect(list2).SequenceEquals(list2); 

Сначала мы получаем intersection из list1 и list2, который { "one", "two", "three" }

Затем используйте SequenceEquals, чтобы определить, что аналогично списку1.

+0

Хотя, я не думаю, что это вполне соответствует случаю в вопросе ... «true, если я сравниваю list2 с list1» – 2010-07-13 20:40:45

+0

@Rex - Это не работает. Это возвращает false, когда оно должно возвращать true. Сравнение list2 с list1 должно возвращать true, потому что list2 имеет те же элементы, что и list1 в том же порядке. Сравнение list3 с list1 должно возвращать false, потому что хотя list3 содержит все элементы в списке1, они не совпадают с порядком. –

+0

@Rex - На самом деле вы были очень близки.Кажется, что работает следующее: list2.Intersect (list1) .SequenceEqual (list1.Take (list2.Count())) –

2

Вы в основном должны перебирать оба списка одновременно. Попробуйте это:

public static bool IsOrderedSubsequenceOf<T>(
    this IEnumerable<T> smallerList, 
    IEnumerable<T> largerList) 
{ 
    IEqualityComparer<T> comparer = Comparer<T>.Default; 

    using (var smallerIterator = smallerList.GetEnumerator()) 
    using (var largerIterator = largerList.GetEnumerator()) 
    { 
     while (smallerIterator.MoveNext()) 
     { 
      T currentTarget = smallerIterator.Current; 
      bool found = false; 
      while (largerIterator.MoveNext()) 
      { 
       T candidate = largerIterator.Current; 
       if (comparer.Equals(currentTarget, candidate)) 
       { 
        found = true; 
        break; 
       } 
      } 
      if (!found) 
      { 
       // Exhausted iterator without finding target. 
       return false; 
      } 
     } 
    } 
    // Found everything in the smaller sequence. Done. 
    return true; 
} 

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

Вы назвали бы его

if (list2.IsOrderedSubsequenceOf(list1)) 

Если вы можете придумать лучшего названия (возможно, положив аргументы наоборот), что было бы хорошо :)

+0

Я хотел бы однажды похитить вас и обменяться мозгами. Я попробую это, спасибо! –

0

Как об этом:

int pos = 0; 
bool result = list1.Count(p => list2.Contains(p) && pos < list2.Length && list2[pos++] == p) == list2.Length; 

Это работает во всех случаях, я считаю. Событие для следующего:

string [] list1 = {"one", "two", "four", "three"};
строка [] list2 = {"one", "two", "three"};

Принятый ответ вернет false, хотя все элементы в списке2 находятся в списке1 в том же порядке.

EDIT: Не работает, если в списке1 есть повторяющиеся значения, содержащиеся в списке2. Согласно комментариям ниже.

+0

Нет, это не подходит для 'string [] list1 = {" three "," one "," two "," four "," three "}; string [] list2 = {"one", "two", "three"}; '. Он запутывается, потому что «три» находится в списке2, но не до конца ... –

+0

Да, это не так, но это потому, что «три» повторяется в списке1. – Klinger

+0

@Klinger: Да, но я не вижу ничего в этом вопросе, чтобы предположить, что это неверный случай. –

Смежные вопросы