2013-07-20 7 views
1

У меня есть два списка, как THW следующие:общие элементы в двух списках, где элементы являются одинаковыми

a=['not','not','not','not'] 
b=['not','not'] 

, и я должен найти len списка, содержащего intesection из двух выше списка, так что результат:

intersection=['not','not'] 
len(intersection) 
2 

Теперь проблема заключается в том, что я пытался filter(lambda x: x in a,b) и filter (lambda x: x in b,a), но когда один из два списка больше, чем другие, я не получаю пересечение, но только проверку членства. В приведенном выше примере, поскольку все члены a находятся в b, я получаю len общих элементов из 4; то, что я вместо этого хочу, является пересечением, которое является len 2. Вместо этого вместо этого будет создан набор, который не является тем, что я хочу, поскольку все элементы одинаковы. Можете ли вы предложить мне какое-нибудь ценное и компактное решение проблемы?

ответ

1

Если вы не возражаете против использования collections.Counter, то вы могли бы иметь решение, как

>>> import collections 
>>> a=['not','not','not','not'] 
>>> b=['not','not'] 

>>> c1 = collections.Counter(a) 
>>> c2 = collections.Counter(b) 

, а затем индекс по 'не'

>>> c1['not'] + c2['not'] 
6 

Для пересечения, вам нужно до

>>> (c1 & c2) ['not'] 
2 
+0

Я думаю, что 'Counter' может быть полезно здесь, но OP хочет 2, а не 6, как результат. Я думал о чем-то более похожем на '(Counter (a) & Counter (b)) [" not "]'. (Или сумма ((счетчик (a) и счетчик (b)). Values ​​()), если мы не хотим жестко кодировать слово.) – DSM

+0

oh oops! Я сделаю редактирование – ersran9

+0

@DSM 'sum ((Counter (a) & Counter (b)). Values ​​())' будет ломаться, если у них более одного слова, не так ли? – ersran9

0

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

intersection является подвигателем более короткого списка (например, b). Теперь для лучшей производительности, когда более короткий список не является очень коротким, сделайте более длинный список набором (например, set(a)). Пересечение может быть выражено в виде списка понимания этих элементов в короткий список, которые также в более набор:

def common_elements(a, b): 
    shorter, longer = (a, b) if len(a)<len(b) else (b, a) 
    longer = set(longer) 
    intersection = [item for item in shorter if item in longer] 
    return intersection 

a = ['not','not','not','not'] 
b = ['not','not'] 
print(common_elements(a,b)) 
+0

Я имел в виду «короче, длиннее = отсортировано ([a, b], key = len)', но это не так приятно, как я думал, это было ... но в любом случае ... –

0

Сделай set. Сначала сделайте эти списки наборами, а затем перейдите на их перекресток. Теперь на пересечении могут быть повторения. Поэтому для каждого элемента в пересечении берутся минимальные повторения в a и b.

>>> a=['not','not','not','not'] 
>>> b=['not','not'] 
>>> def myIntersection(A,B): 
...  setIn = set(A).intersection(set(B)) 
...  rt = [] 
...  for i in setIn: 
...   for j in range(min(A.count(i),B.count(i))): 
...    rt.append(i) 
...  return rt 
... 
>>> myIntersection(a,b) 
['not', 'not'] 
0

Рассматривали ли вы следующий подход?

a = ['not','not','not','not'] 
b = ['not','not'] 

min(len(a), len(b)) 
# 2 

Поскольку все элементы одинаковы, количество общих элементов - это минимальная длина обоих списков.

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