2014-10-31 4 views
0

У меня есть список фруктов:Как найти пересечение списка и вложенного списка?

fruits = ["apple","banana"] 

У меня также есть вложенный список корзин, в котором каждый список содержит строку (имя корзины) и список фруктов.

baskets = [["basket1",["apple","banana","pear","strawberry"]],["basket2",["strawberry","pear","peach"]],["basket3",["peach","apple","banana"]]] 

Я хотел бы знать, какие наборы содержат каждые фрукты в плодах списка: результат я ожидаю список с двумя элементами, «корзины1» и «basket3».

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

myset = set(fruits).intersection(*map(set, set(baskets))) 

Но я получаю TypeError «unhashable типа:" список». Я понимаю, что я не могу сопоставлять списки, но я думал, что использование функции «set» в обоих списках приведет к их преобразованию в набор ... есть ли другой способ найти пересечение списка и список списков?

+2

почему бы вам не использовать словарь для корзин? – Sasa

+0

@Sasa Это имеет значение? – kormak

+0

@kormak: В этом случае не _huge_, но да. Вместо того, чтобы смотреть на второй элемент каждого списка в списке 'baskets', вы просто посмотрите на каждое значение в dict' baskets'. В общем, использование правильной структуры данных для работы облегчает вашу жизнь. – abarnert

ответ

4

Вы можете заколебать корзины и проверить, установлен ли набор fruits фруктов в текущей корзине, если да, сохраните имя текущей корзины.

>>> fruits = {"apple", "banana"} #notice the {}, or `set(["apple","banana"])` in Python 2.6 or earlier 
>>> [b for b, f in baskets if fruits.issubset(f)] 
['basket1', 'basket3'] 
+0

Я получаю следующую ошибку: AttributeError: объект «list» не имеет атрибута «issubset» Док говорит, что issubset применяется к наборам, мне нужно преобразовать списки в наборы? Если да, то как? Как я уже упоминал в своем посте, использование набора (фрукты) или набора (корзин) вызывает ошибку типа нераспаковывающегося типа. – kormak

+1

@kormak: Нет, 'set (fruits)' не вызывает ошибку типа «неубираемый тип», это 'set (baskets)', который делает это, чего не делает Ashwini. (Вот почему кодирование кучи выражений в одно большое выражение делает более сложной отладку. Вы не знаете, какой из этих вызовов вызывает 'set'.) – abarnert

+1

@kormak: Также обратите внимание, что Ashwini определяет« фрукты »как в первую очередь, поэтому проблема даже не возникает. – abarnert

0

Вы не можете использовать хеш-коды больше, чем вы можете хеш-списки. У них обоих одинаковые проблемы: поскольку они изменяемы, значение может изменять его содержимое, делая любой набор, содержащий его как член или любой словарь, который содержит его как ключ, неожиданно недействительный.

Вы могут хешировать неизменные эквиваленты обоих, tuple и frozenset.

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

myset = set(fruits).intersection(*map(set, set(baskets))) 

Первая часть заключается в следующем:

baskets_set = set(baskets) 

У вас есть список списков. Вы, set(baskets), пытаетесь создать список списков. Что вы не можете сделать, потому что списки не хешируются.


Если вы только что удалили это, и использовали map(set, baskets), вы бы тогда итератор множеств, который является совершенно действительной вещью.

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


Плюс, даже если вы решите это, логика все еще не имеет никакого смысла. Каково пересечение множества, скажем, 3 строк с множеством, скажем, 3 (замороженных) наборов строк? Пусто. Эти два набора не имеют общих элементов. Тот факт, что некоторые элементы второго могут содержать элементы первого, не означает, что второй сам содержит любые элементы первого.

0

Вы могли бы сделать это таким образом, используя свой подход:

fruits = ["apple","banana"] 
baskets = [["basket1",["apple","banana","pear","strawberry"]], 
      ["basket2",["strawberry","pear","peach"]], 
      ["basket3",["peach","apple","banana"]]] 

fruitset = set(fruits) 
res = set(b for b, s in ((b, set(c)) for b, c in baskets) if s & fruitset) 
print res # --> set(['basket1', 'basket3'])