识别列表长度相似性的最佳方法

时间:2011-10-19 18:45:18

标签: python algorithm list

我的 dict 包含其键下的列表:

dct = {'a': [1, 2, 3],
       'b': [1, 2, 3, 4],
       'c': [1, 2]}

识别列表长度是否相同的最佳方式是什么?

这是我的解决方案:

import itertools
len(set(itertools.imap(len, dct.viewvalues()))) == 1

True如果相似,False如果不是

UPD:参考@RaymondHettinger建议将map替换为itertools.imap

4 个答案:

答案 0 :(得分:6)

您的解决方案看起来很好。

如果您想稍微调整一下,请使用 itertools.imap()而不是 map()。这会将内存占用减少到O(1)而不是O(n)。

答案 1 :(得分:4)

首先,我会坚持itervalues,它使用简单的评估。

其次,我会谨慎依赖于使用set,因为它会在每次遍历字典时执行查找集合中的值。超出时间为O(1)(如果所有长度相同,则O(n)更糟糕的情况是O(1),如果所有长度都不同则为O(n) )根据docs。但是很难评估使用set的开销。

在这种情况下,我会使用allall在找到第一个False值时失败。因此,长度的第一个不匹配将停止交互过程。但是,如果使用set,它会通过所有列表到达结尾,然后才将其长度与1进行比较。

>>> dct = {'a': [1, 2, 3],
       'b': [1, 2, 3, 4],
       'c': [1, 2]}
>>> lenght_1 = len(dct.itervalues().next())
>>> all(len(value)==lenght_1 for value in dct.itervalues())
False

>>> dct = {'a': [1, 2, 3],
       'b': [1, 2, 4],
       'c': [1, 2, 5]}
>>> lenght_1 = len(dct.itervalues().next())
>>> all(len(value)==lenght_1 for value in dct.itervalues())
True

可以使用相同的迭代器it来优化代码,该迭代器不会经过两次第一个值:

>>> it = dct.itervalues()
>>> length_1 = len(next(it))
>>> all(len(value)==l1 for value in it)
True

答案 2 :(得分:2)

注意:ovgolovin's solution要好得多。我在这里留下这个答案,因为有讨论引用它。

您的解决方案很好,但您可以使用生成器表达式,它使用更少的内存并且更具可读性:

len(set(len(x) for x in dct.viewvalues()))) == 1

答案 3 :(得分:1)

正如Michael J. Barber在对the answer的评论中所建议的那样,这是使用groupby模块中的imapitertools的代码。

imap只会将len函数应用于每个列表。

groupby只是以相同长度的块来摸索值。

因此,如果长度不止一个,则长度不同。如果只有一个长度的chuck,这意味着,列表的长度是相同的,第二次访问groupby迭代器应该产生StopIteration,从而返回None(默认next函数的值。

此代码的好处是imapgroupby是用C语言编写的,而且速度非常快。

from itertools import imap,groupby

dct = {'a': [1, 2, 3],
       'b': [1, 2, 3, 4],
       'c': [1, 2]}

dct2 = {'a': [1, 2, 3],
       'b': [1, 2, 34],
       'c': [1, 2, 5]}

def check_lenghts(iterable):
    it = groupby(imap(len,iterable.itervalues()))
    next(it,None)
    return True if next(it,None)==None else False

print(check_lenghts(dct))
print(check_lenghts(dct2))