【问题标题】:Efficiently comparing the first item in each list of two large list of lists?有效地比较两个大列表中每个列表中的第一项?
【发布时间】:2016-11-17 19:35:58
【问题描述】:

我目前正在处理大量列表(~280k 列表)和一个较小的列表(~3.5k 列表)。我正在尝试有效地将较小列表中的第一个索引与大列表中的第一个索引进行比较。如果它们匹配,我想从具有匹配第一个索引的小型和大型列表中返回两个列表。

例如:

大名单1:

[[a,b,c,d],[e,f,g,h],[i,j,k,l],[m,n,o,p]]

小清单2:

[[e,q,r,s],[a,t,w,s]]

会回来

[([e,q,r,s],[e,f,g,h]),([a,t,w,s],[a,b,c,d])]

我目前的设置如下所示,其中返回一个元组列表,每个元组包含具有匹配第一个元素的两个列表。我对正在使用的任何其他数据结构都很好。我试图使用一组元组,但在试图找出比我已经拥有的更快的方法时遇到了问题。

我用来比较这两个列表的代码目前是这样的:

match = []
for list_one in small_list:
    for list_two in large_list:
        if str(list_one[0]).lower() in str(list_two[0]).lower():
            match.append((spm_values, cucm_values))
            break
return match

【问题讨论】:

  • 当其中一个列表有多个以相同值开头的子列表时会发生什么?或者那是不可能的
  • 在这种情况下不会发生 - 第一个元素是 MAC 地址。
  • 首先,in 运算符不是检查相等性的正确方法,您应该为此目的使用==。其次,为什么要将第一项转换为 str
  • 好点,不知道为什么我没有使用==。 str() 会大大减慢速度吗?
  • 这些列表的维度是否相同?如果是这样,您也许可以使用numpy 的扩展列表切片及其改进的执行速度来解决哪些列表问题

标签: python list python-3.x


【解决方案1】:

我实际上使用的是 Python 2.7.11,尽管我猜这可能会起作用。

l1 =[['a','b','c','d'],['e','f','g','h'],['i','j','k','l'],['m','n','o','p']]
l2 =[['e','q','r','s'],['a','t','w','s']]

def org(Smalllist,Largelist):
    L = Largelist
    S = Smalllist
    Final = [] 
    for i in range(len(S)):
        for j in range(len(L)):
            if S[i][0] == L[j][0]:
                Final.append((S[i],L[j]))
    return Final

我建议您将 Smaller 列表放在第一个变量中,以便按照您预期的顺序获得结果。

像我一样在测试时将这些字母作为字符串输入是非常重要的,否则它们可能会被视为变量,代码将无法正常运行。

【讨论】:

    【解决方案2】:

    假设顺序无关紧要,我强烈建议使用字典将前缀(一个字符)映射到项目并使用set 来查找匹配项:

    # generation of data... not important
    >>> lst1 = [list(c) for c in ["abcd", "efgh", "ijkl", "mnop"]]
    >>> lst2 = [list(c) for c in ["eqrs", "atws"]]
    
    # mapping prefix to list (assuming uniqueness)
    >>> by_prefix1 = {chars[0]: chars for chars in lst1}
    >>> by_prefix2 = {chars[0]: chars for chars in lst2}
    
    # actually finding matches by intersecting sets (fast)
    >>> common = set(by_prefix1.keys()) & set(by_prefix2.keys())
    >>> tuples = tuple(((by_prefix1[k], by_prefix2[k]) for k in common))
    >>> tuples
    

    【讨论】:

    • 你打败了我:P
    • 由于某种原因,当将前缀映射到大型列表的列表 (by_prefix2) 时,它会丢失大约 60k 个条目
    • 我的猜测是前缀不是唯一的,这导致它只保留最后一个值。
    • 是的,我的错。我很困惑,因为没有找到共同的值,但这是因为我们正在比较的值中有几个字母大写。谢谢!
    【解决方案3】:

    这是一个使用列表理解的单行。不过,我不确定它的效率如何。

    large = [list(c) for c in ["abcd", "efgh", "ijkl", "mnop"]]
    small = [list(c) for c in ["eqrs", "atws"]]
    ret = [(x,y) for x in large for y in small if x[0] == y[0]]
    
    print ret
    #output
    [(['a', 'b', 'c', 'd'], ['a', 't', 'w', 's']), (['e', 'f', 'g', 'h'], ['e', 'q', 'r', 's'])]
    

    【讨论】:

    • 这比@Reut Sharabani 的回答效率低一些,因为你的理解是 O(XY) 而他的理解是 O((X+Y)log(XY) ) 因为集合数学和字典
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    • 1970-01-01
    • 2017-05-11
    • 1970-01-01
    相关资源
    最近更新 更多