[英]Find the closest matching elements in a list of lists
I have 2 list of lists(namely list_1
and list_2
) that I need to check for similarities. 我有2个列表列表(即
list_1
和list_2
),需要检查它们的相似性。 I want to track the highest number of matches and get the indexes of list_1 and list_2 with the highest matches. 我想跟踪最高匹配数,并获取具有最高匹配数的list_1和list_2的索引。
Note: Highest matches can be more than 1 since the highest number of matches can occur again(duplicate). 注意:最高匹配数可以大于1,因为最高匹配数可以再次出现(重复)。
I have tried to find the highest using max
function, but it doesn't give me the other highest duplicate values. 我试图使用
max
函数找到最高的max
,但是它没有给我其他最高的重复值。
list_of_similarities = []
def similarities():
print("SIMILARITIES")
for i in range(len(list_1)):
for j in range(len(list_2)):
if set(list_2[j]) & set(list_1[i]):
matchingValues = set(list_2[j]) & set(list_1[i])
print('list_1[{}], list_2[{}]'.format(i, j), 'matching value:',set(list_2[j]) & set(list_1[i]))
list_of_similarities.append(matchingValues)
print("")
print("")
print("The maximum matches found are:")
print(max(list_of_similarities))
list_of_similarities.clear()
list_1 = [['a','b','c'],['d','e','g'],['l','r'],['z']]
list_2 = [['b','c'], ['l','e','a'], ['f'], ['z','r'], ['x', 'b', 'c']]
CURRENT RESULT 当前结果
# list_1[0], list_2[0] matching value: {'b', 'c'}
# list_1[0], list_2[1] matching value: {'a'}
# list_1[0], list_2[4] matching value: {'b', 'c'}
# The maximum matches found are:
# {'b', 'c'}
# list_1[1], list_2[1] matching value: {'e'}
# The maximum matches found are:
# {'e'}
# list_1[2], list_2[1] matching value: {'l'}
# The maximum matches found are:
# {'l'}
# list_1[2], list_2[3] matching value: {'r'}
# The maximum matches found are:
# {'r'}
# list_1[3], list_2[3] matching value: {'z'}
# The maximum matches found are:
# {'z'}
EXPECTED RESULT 预期结果
# list_1[0], list_2[0] matching value: {'b', 'c'}
# list_1[0], list_2[1] matching value: {'a'}
# list_1[0], list_2[4] matching value: {'b', 'c'}
# The maximum matches found are:
# {'b', 'c'}
# The list_1 and list_2 indexes for highest matches are:
# [0,[0, 4]]
# list_1[1], list_2[1] matching value: {'e'}
# The maximum matches found are:
# {'e'}
# The list_1 and list_2 indexes for highest matches are:
# [1,[1]]
# list_1[2], list_2[1] matching value: {'l'}
# The maximum matches found are:
# {'l'}
# The list_1 and list_2 indexes for highest matches are:
# [2,[1]]
# list_1[2], list_2[3] matching value: {'r'}
# The maximum matches found are:
# {'r'}
# The list_1 and list_2 indexes for highest matches are:
# [2,[3]]
# list_1[3], list_2[3] matching value: {'z'}
# The maximum matches found are:
# {'z'}
# The list_1 and list_2 indexes for highest matches are:
# [3,[3]]
list_of_similarities = []
def similarities():
print("SIMILARITIES")
for i in range(len(list_1)):
idx_list2 = []
for j in range(len(list_2)):
if set(list_2[j]) & set(list_1[i]):
matchingValues = set(list_2[j]) & set(list_1[i])
print('list_1[{}], list_2[{}]'.format(i, j), 'matching value:',set(list_2[j]) & set(list_1[i]))
list_of_similarities.append(matchingValues)
print("The maximum matches found are:")
print(max(list_of_similarities))
val = max(list_of_similarities)
for idx, item in enumerate(list_2):
# check if item contains all elements in val
result = all(elem in item for elem in list(val))
if result:
idx_list2.append(idx)
print ("The list_1 and list_2 indexes for highest matches are:")
print ([i,idx_list2])
print ("")
list_of_similarities.clear()
list_1 = [['a','b','c'],['d','e','g'],['l','r'],['z']]
list_2 = [['b','c'], ['l','e','a'], ['f'], ['z','r'], ['x', 'b', 'c']]
similarities()
output: 输出:
SIMILARITIES
list_1[0], list_2[0] matching value: {'c', 'b'}
list_1[0], list_2[1] matching value: {'a'}
list_1[0], list_2[4] matching value: {'c', 'b'}
The maximum matches found are:
{'c', 'b'}
The list_1 and list_2 indexes for highest matches are:
[0, [0, 4]]
list_1[1], list_2[1] matching value: {'e'}
The maximum matches found are:
{'e'}
The list_1 and list_2 indexes for highest matches are:
[1, [1]]
list_1[2], list_2[1] matching value: {'l'}
list_1[2], list_2[3] matching value: {'r'}
The maximum matches found are:
{'l'}
The list_1 and list_2 indexes for highest matches are:
[2, [1]]
list_1[3], list_2[3] matching value: {'z'}
The maximum matches found are:
{'z'}
The list_1 and list_2 indexes for highest matches are:
[3, [3]]
The Zen of Python asserts that 'Flat is better than nested', so this approach to the problem doesn't use an explicit nested loop. Python的Zen断言“扁平比嵌套好”,因此这种解决问题的方法没有使用显式的嵌套循环。 Having said that, there is a lot of looping in comprehensions, so it might well be slower than using nested for loops.
话虽如此,理解中存在很多循环,因此它可能比使用嵌套的for循环要慢。
It uses itertools.product to create the pairs for matching. 它使用itertools.product创建用于匹配的对。
>>> pairs = itertools.product(['a', 'b'], [1, 2])
>>> for p, q in pairs:print(p, q)
...
a 1
a 2
b 1
b 2
and itertools.groupby to group the pairs by the element from the first list: 和itertools.groupby以根据第一个列表中的元素将对分组:
>>> pairs = itertools.product(['a', 'b'], [1, 2])
>>> for k, g in itertools.groupby(pairs, key=lambda x: x[0]):
... print(k, list(g))
...
a [('a', 1), ('a', 2)]
b [('b', 1), ('b', 2)]
When calling max
on a list of (frozen) sets it specifies that max
must use the length of the set. 在(冻结)集合列表上调用
max
,它指定max
必须使用集合的长度。 This is because by default, a set's greater than operation returns whether the set is a superset of another, not whether it is longer 这是因为默认情况下,一个集合的大于操作返回该集合是否是另一个集合的超集,而不是它是否更长
>>> set([1, 2]) > set([3, 4, 5])
False
>>> max([set([1, 2]), set([1, 2, 3]), set([4, 5, 6, 7, 8, 9])])
{1, 2, 3}
>>> max([set([1, 2]), set([1, 2, 3]), set([4, 5, 6, 7, 8, 9])], key=len)
{4, 5, 6, 7, 8, 9}
This approach correctly reports all "longest" matches if there is more than one. 如果存在多个,则此方法可以正确报告所有“最长”的匹配项。 Matches are stored as frozensets so that they may be easily deduplicated if a match occurs more than once.
匹配项被存储为冻结集,因此,如果匹配项不止一次,则可以很容易地对它们进行重复数据删除。
import itertools
def similarities():
# Create format strings.
matched_fmt = 'list_1[{}], list_2[{}] matching value: {}'
index_fmt = '[{}, {}]'
print("SIMILARITIES")
# Get the cartesian product of the two lists.
product = itertools.product(list_1, list_2)
# Iterate over the product, grouping by the element in the first list.
# Enumerate the iteration so that we know the index of the item in the first list.
for i, (_, g) in enumerate(itertools.groupby(product, key=lambda x: x[0])):
# List all matches and the index of the second list element.
matches = [(j, frozenset(p) & frozenset(q)) for (j, (p, q)) in enumerate(g)]
# Find the longest matches.
longest = len(max(matches, key=lambda x: len(x[1]))[1])
longest_matches = [(idx, match) for (idx, match) in matches
if len(match) == longest]
found_matches = [(idx, match) for (idx, match) in matches if match]
unique_matches = {match for (_, match) in longest_matches}
# Report.
found_lines = [matched_fmt.format(i, index, match)
for index, match in found_matches]
print('\n'.join(found_lines))
print("The maximum matches found are:")
print(' '.join(str(match) for match in unique_matches))
print('The list_1 and list_2 indexes for the highest matches are:')
print(index_fmt.format(i, [index for (index, _) in longest_matches]))
print()
The function produces this output: 该函数产生以下输出:
SIMILARITIES
list_1[0], list_2[0] matching value: frozenset({'c', 'b'})
list_1[0], list_2[1] matching value: frozenset({'a'})
list_1[0], list_2[4] matching value: frozenset({'c', 'b'})
The maximum matches found are:
frozenset({'c', 'b'})
The list_1 and list_2 indexes for the highest matches are:
[0, [0, 4]]
list_1[1], list_2[1] matching value: frozenset({'e'})
The maximum matches found are:
frozenset({'e'})
The list_1 and list_2 indexes for the highest matches are:
[1, [1]]
list_1[2], list_2[1] matching value: frozenset({'l'})
list_1[2], list_2[3] matching value: frozenset({'r'})
The maximum matches found are:
frozenset({'r'}) frozenset({'l'})
The list_1 and list_2 indexes for the highest matches are:
[2, [1, 3]]
list_1[3], list_2[3] matching value: frozenset({'z'})
The maximum matches found are:
frozenset({'z'})
The list_1 and list_2 indexes for the highest matches are:
[3, [3]]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.