2012-02-07 2 views
1

Рассмотрим у нас есть эти три списка:Linq список запросов содержит список с того же порядка

List<string> l1= new List<string>(){"A","B","C"}; 
    List<string> l2= new List<string>(){"A","C","B"}; 

    List<string> l3= new List<string>(){"B","C"}; 

Мне нужно LINQ запрос, который включает в себя сказать l1 l3, но l2 не делает.

+0

может быть дубликатов? – BrokenGlass

+0

да, у нас может быть дубликат. – Behnam

ответ

6

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

public static bool ContainsSequence<T>(this IEnumerable<T> source, 
             IEnumerable<T> other) 
{ 
    int count = other.Count(); 

    while (source.Any()) 
    { 
     if (source.Take(count).SequenceEqual(other)) 
      return true; 
     source = source.Skip(1); 
    } 
    return false; 
} 

Обратите внимание, что это будет O (п), так худшем случае вы полностью перечислить other перечисления для каждого элемента в коллекции source.

Теперь вы можете сделать:

List<string> l1 = new List<string>() { "A", "B", "C" }; 
List<string> l2 = new List<string>() { "A", "C", "B" }; 
List<string> l3 = new List<string>() { "B", "C" }; 

bool l1ContainsL2 = l1.ContainsSequence(l2); //returns false 
bool l1ContainsL3 = l1.ContainsSequence(l3); //returns true 
2

должны быть просто:

l1.Intersect(l3).Except(l2); 

Примечания:
в зависимости от размеров L2 и L3 обратный порядок может быть более эффективным.
Учитывая ваши конкретные значения, ничего не будет возвращено, поскольку в l1 ничего нет, чего нет в l3.

2

Exclaimer: Как BrokenGlass указывает, что не ясно, что это означает, что список содержит другой. Здесь я допускаю, чтобы содержащая последовательность имела дополнительные элементы между элементами содержащейся последовательности.

Быстрый с точки зрения ввода, не слишком эффективно:

bool l1contains = l1.Where(x => l3.Contains(x)).ToList().SequenceEqual(l3); 
bool l2contains = l2.Where(x => l3.Contains(x)).ToList().SequenceEqual(l3); 

Более эффективно - так эффективно, как это может быть, работает в O (т + п), где т, п длины списков.

private static bool ContainsOrdered<T>(IEnumerable<T> containing, IEnumerable<T> contained) 
{ 
    var e1 = containing.GetEnumerator(); 
    var e2 = contained.GetEnumerator(); 
    bool hasmore1 = e1.MoveNext(); 
    bool hasmore2 = e2.MoveNext(); 

    while (hasmore1 && hasmore2) 
    { 
     while (hasmore1 && !e1.Current.Equals(e2.Current)) 
      hasmore1 = e1.MoveNext(); 
     if (hasmore1) // Currents are equal 
     { 
      hasmore1 = e1.MoveNext(); 
      hasmore2 = e2.MoveNext(); 
     } 
    } 

    return !hasmore2; 
} 

bool contains1 = ContainsOrdered(l1, l3); 
bool contains2 = ContainsOrdered(l2, l3); 
+0

неправильный, так как он будет соответствовать, например. для l1 = '{1,2,4,3}' и l2 = '{1,2,3}' – BrokenGlass

+0

@BrokenGlass - это точка, не так ли? То, что l1 содержит l2 означает, в моем oppinion – voidengine

+0

Mhh Я понял, что это означает только * непрерывное совпадение последовательности, но вы можете быть правы. ОП должен уточнить – BrokenGlass

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