Output similarities found in two list

时间:2018-02-03 11:13:29

标签: python list data-structures syntax

Two questions. 1.My code contain two list

ListA = [[3, 5], [4, 4], [4, 5], [4, 6], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [6, 4], [6, 5], [6, 6], [7, 5]]

ListB =[[0, 4], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6], [5, 2], [5, 3], [5, 4], [5, 5], [5, 6], [6, 4]]

I want it to output the similarities found between the two list:

[[3,5][4,4][4,5][4,6][5,3][5,4][5,5][5,6][6,4]]

print(set(ListA]).intersection(ListB])) didn't work. Any other solutions?

2. I would also like it to output the numbers that are similar in index[0] of each brackets of two number found in both list.

ListA contain [3,5][4,4][5,3][6,4] ListB contain [3,1][4,2][5,2][6,4]

Since 3,4,5,6 is found in index[0] (Or first number) of each bracket, the output would be.

[3,4,5,6]

How would I do that?

5 个答案:

答案 0 :(得分:2)

Lists are not hashable, so you have to convert to tuple1) if you want to use set.intersection:

>>> set(map(tuple, ListA)).intersection(map(tuple, ListB))
set([(6, 4), (5, 4), (4, 6), (4, 5), (4, 4), (5, 5), (5, 6), (3, 5), (5, 3)])

And back to list, if you want:

>>> sorted(map(list, set(map(tuple, ListA)).intersection(map(tuple, ListB))))
[[3, 5], [4, 4], [4, 5], [4, 6], [5, 3], [5, 4], [5, 5], [5, 6], [6, 4]]

Once you have that, you can get a set of the first elements for your second part.

>>> set(x[0] for x in _)  # _ being the previous result
{3, 4, 5, 6}

This may seem a bit complicated, but using set it's faster, O(n), than a linear search in the entire list for each element, being O(n²).


Without using set.intersection, you could also use a list comprehension to filter those elements in ListB that are also in ListA (or vice versa), but again, you should convert the other list to a set so the lookup is faster (O(1) instead of O(n)), and for this, you again have to convert to tuple. (In this case, you could also convert to repr and compare those, but I tried both and tuple seems to be much faster.)

>>> setA = set(map(tuple, ListA))
>>> [b for b in ListB if tuple(b) in setA]
[[3, 5], [4, 4], [4, 5], [4, 6], [5, 3], [5, 4], [5, 5], [5, 6], [6, 4]]

This also has the advantage of retaining the original order of the elements in ListB and is also a bit faster. Alternatively, you could create a dictionary mapping the first elements in the list to sets of the respective second elements, and then use a list comprehension, checking in that dict whether the element exists.

dictA = {}
for (x, y) in ListA:
    dictA.setdefault(x, set()).add(y)
common = [b for b in ListB if b[0] in dictA and b[1] in dictA[b[0]]]

This should be equally fast, i.e. O(n), and might need a bit less memory for creating all those sets (depending on the elements in the list).


1) Or any other unambiguous hashable representation of the lists, but tuple really seems to be the only viable option. frozenset does not care about the order of elements, and while you could convert to the lists repr and eval back after the intersection, you really shouldn't.

答案 1 :(得分:2)

你可以使用这样的列表理解:

listA = [[4, 4], [4, 5], [4, 6], [5, 4], [5, 5], [5, 6], [6, 4], [6, 5], [6, 6]]
listB = [[1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6], [5, 2], [5, 3], [5, 4], [5, 5], [5, 6]]

common = [i for i in listA if i in listB]

它可能不是最快的方法,但除非您使用大型列表,否则它很好。

答案 2 :(得分:0)

Your original idea doesn't work because you can't have lists in sets, as they aren't hashable. An easy way is to turn your lists into tuples :

ListA = [[4, 4], [4, 5], [4, 6], [5, 4], [5, 5], [5, 6], [6, 4], [6, 5], [6, 6]]
ListB =[[0, 4], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6], [5, 2], [5, 3], [5, 4], [5, 5], [5, 6], [6, 4]]

set_a = set([tuple(l) for l in ListA])
set_b = set([tuple(l) for l in ListB])

intersection = set_a.intersection(set_b)
print(intersection)
# {(6, 4), (5, 4), (4, 6), (5, 5), (4, 5), (5, 6), (4, 4)}

# or, if you prefer a list of lists
print([list(t) for t in intersection])
# [[6, 4], [5, 4], [4, 6], [5, 5], [4, 5], [5, 6], [4, 4]]

答案 3 :(得分:0)

您可以使用简单的嵌套循环。示例是here

firstIsEqual = set()
allEquals = []

for Av1, Av2 in ListA:
  for Bv1, Bv2 in ListB:
    if Av1 == Bv1:
      firstIsEqual.add(Av1)
      if Av2 == Bv2:
        allEquals.append([Av1, Av2])

print(firstIsEqual)
print(allEquals)

答案 4 :(得分:0)

第二部分有些混乱,你在找这个吗?

ListA = [[3, 5], [4, 4], [4, 5], [4, 6], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [6, 4], [6, 5], [6, 6], [7, 5]]

ListB =[[0, 4], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6], [5, 2], [5, 3], [5, 4], [5, 5], [5, 6], [6, 4]]

from itertools import groupby
def similiraty(list_1,list_2):
    final_list = [i for i in list_1 if i in list_2]
    for a,b in groupby(final_list,lambda x:x[0]):
        print({a:list(b)})





print(similiraty(ListB,ListA))

输出:

{3: [[3, 5]]}
{4: [[4, 4], [4, 5], [4, 6]]}
{5: [[5, 3], [5, 4], [5, 5], [5, 6]]}
{6: [[6, 4]]}

或简单地说:

return [a for a,b in groupby(final_list,lambda x:x[0])]

输出:

[3, 4, 5, 6]