2014-08-28 3 views
7

Можете ли вы предоставить мне (возможно, идиоматический) способ проверить, является ли список A подсписком данного списка B?Проверить наличие подписок

E.g.

isSubList(List(1,2), List(1,2,3,4)) // => true 
isSubList(List(1,2), List(5,6,7,8)) // => false 
+3

Непонятно, хотите ли вы подмножество или фрагмент. Например, это «Список (1,3)» подписок «Список (1,2,3)» (он был бы подсписком «Список (1,3,5)», ясно)? –

+0

Дублирующий вопрос см. Http://stackoverflow.com/a/3650325/1586965 – samthebest

ответ

8

Один из способов будет использовать forall и contains:

scala> List(1, 2).forall(List(1, 2, 3, 4).contains) 
res3: Boolean = true 

scala> List(1, 2).forall(List(5, 6, 7, 8).contains) 
res4: Boolean = false 

scala> List(1, 2).forall(List(5, 6, 2, 9).contains) 
res5: Boolean = false 

Заметьте, что этот подход не учитывает порядок:

scala> List(1, 2).forall(List(2, 1).contains) 
res6: Boolean = true 

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

+0

На практике не следует помещать что-то вроде 'List (1, 2, 3, 4)' внутри лямбды, поскольку оно создаст список и над. – samthebest

12

Если порядок имеет значение вы можете использовать containsSlice, которые проверить, является ли коллекциям содержит заданную последовательность как срез

def isSubList[A](l1:List[A], l2:List[A]) = l2.containsSlice(l1) 
1

еще одно решение:

def isSubList[A](short: List[A], long: List[A]): Boolean = 
    long.tails exists (_.startsWith(short)) 

Однако, это было бы гораздо более эффективным, если списки были сначала преобразованы в потоки:

def isSubList[A](short: List[A], long: List[A]): Boolean = { 
    val sLong = long.toStream 
    val sShort = short.toStream 
    sLong.tails exists (_.startsWith(sShort)) 
} 

Таким образом, не все хвосты h ave, который должен быть сгенерирован. Также запускается с оценкой короткого замыкания

+0

'Iterator' и' view' также будут работать. – samthebest

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