通过每个项目的两个第一个值优化列表列表中的频率
optimizing frequency in a list of list, by each item's two first value
我完全不熟悉编程(不到 2 个月 - self-taught),我正在做一个项目,它需要每个内部的前两个索引的列表列表的频率列表。
这是我的清单:
x = [['block', 3], ['street', 2], ['lamp',1], ['street', 2],
['industrial', 3], ['park', 2], ['park', 3], ['industrial', 3],
['block', 3], ['street', 2], ['lamp',1], ['street', 2], ['industrial',
3], ['park', 2]]
所以每个内部列表的第一个值是标题,第二个是约定值。
重要的是,如您所见,其中一些重复(重复)。
我想要一个这样的输出列表:
p = [['block', 3, 2], ['street', 2, 4], ['lamp', 1, 2], ['industrial',
3, 3], ['park', 2, 2], ['park', 3, 1]]
在外部列表 x 中,第三个值作为该内部列表的 FREQUENCY。
所以这是我的 non-pythonic(可能很乏味)方法:
x = [['block', 3], ['street', 2], ['lamp',1], ['street', 2], ['industrial', 3], ['park', 2], ['park', 3], ['industrial', 3], ['block', 3], ['street', 2], ['lamp',1], ['street', 2], ['industrial', 3], ['park', 2]]
p = []
for a in x:
p.append(a ), a.append( x.count(a))
print p # checkpoint
i= 0
while i < len(p):
for j in range(len(p)):
if i == j:
print i, ' = ', j
break
else:
if p[i][:2] == p[j][:2]:
print p[i][:2], '==', p[j][:2]
p.pop(i)
i = 0
j=0
break
i = i+1
print p # the list of lists I'm desired
但是对于我的项目来说,因为这个函数跟在其他函数之后,与它们相比这个函数具有更高的run-time,尤其是在输入数据集很大的情况下。
因为我缺乏知识,所以无法优化我编写的代码。
所以我想问一下,有没有更快更 pythonic 的方法来做到这一点?
是的,用字典。我假设顺序很重要,所以我将使用OrderedDict
,但如果顺序无关紧要,您可以考虑使用Counter
对象:
>>> from collections import OrderedDict
>>> counter = OrderedDict()
>>> for a, b in x:
... t = (a, b)
... counter[t] = counter.get(t, 0) + 1
...
>>> final = [[a, b, v] for (a,b),v in counter.items()]
>>> final
[['block', 3, 2], ['street', 2, 4], ['lamp', 1, 2], ['industrial', 3, 3], ['park', 2, 2], ['park', 3, 1]]
刚刚注意到你在 Python 2(如果你能帮助它,你真的应该使用 Python 3),在这种情况下,因为你在 Python 2 , 你应该使用 counter.iteritems()
而不是 counter.items()
.
所以像这样:
>>> final = [[a, b, count] for (a, b), count in counter.iteritems()]
>>> final
[['block', 3, 2], ['street', 2, 4], ['lamp', 1, 2], ['industrial', 3, 3], ['park', 2, 2], ['park', 3, 1]]
请注意,您的第一个 for 循环是按二次缩放的,至于那个 while 循环,我不想考虑它,我认为也可能是二次的,但也许更糟(因为您 .pop(i)
) 但我在上面发布的解决方案是线性扩展的。所以它应该能够有效地处理更大的数据集。
我完全不熟悉编程(不到 2 个月 - self-taught),我正在做一个项目,它需要每个内部的前两个索引的列表列表的频率列表。
这是我的清单:
x = [['block', 3], ['street', 2], ['lamp',1], ['street', 2], ['industrial', 3], ['park', 2], ['park', 3], ['industrial', 3], ['block', 3], ['street', 2], ['lamp',1], ['street', 2], ['industrial', 3], ['park', 2]]
所以每个内部列表的第一个值是标题,第二个是约定值。
重要的是,如您所见,其中一些重复(重复)。
我想要一个这样的输出列表:
p = [['block', 3, 2], ['street', 2, 4], ['lamp', 1, 2], ['industrial', 3, 3], ['park', 2, 2], ['park', 3, 1]]
在外部列表 x 中,第三个值作为该内部列表的 FREQUENCY。
所以这是我的 non-pythonic(可能很乏味)方法:
x = [['block', 3], ['street', 2], ['lamp',1], ['street', 2], ['industrial', 3], ['park', 2], ['park', 3], ['industrial', 3], ['block', 3], ['street', 2], ['lamp',1], ['street', 2], ['industrial', 3], ['park', 2]]
p = []
for a in x:
p.append(a ), a.append( x.count(a))
print p # checkpoint
i= 0
while i < len(p):
for j in range(len(p)):
if i == j:
print i, ' = ', j
break
else:
if p[i][:2] == p[j][:2]:
print p[i][:2], '==', p[j][:2]
p.pop(i)
i = 0
j=0
break
i = i+1
print p # the list of lists I'm desired
但是对于我的项目来说,因为这个函数跟在其他函数之后,与它们相比这个函数具有更高的run-time,尤其是在输入数据集很大的情况下。
因为我缺乏知识,所以无法优化我编写的代码。
所以我想问一下,有没有更快更 pythonic 的方法来做到这一点?
是的,用字典。我假设顺序很重要,所以我将使用OrderedDict
,但如果顺序无关紧要,您可以考虑使用Counter
对象:
>>> from collections import OrderedDict
>>> counter = OrderedDict()
>>> for a, b in x:
... t = (a, b)
... counter[t] = counter.get(t, 0) + 1
...
>>> final = [[a, b, v] for (a,b),v in counter.items()]
>>> final
[['block', 3, 2], ['street', 2, 4], ['lamp', 1, 2], ['industrial', 3, 3], ['park', 2, 2], ['park', 3, 1]]
刚刚注意到你在 Python 2(如果你能帮助它,你真的应该使用 Python 3),在这种情况下,因为你在 Python 2 , 你应该使用 counter.iteritems()
而不是 counter.items()
.
所以像这样:
>>> final = [[a, b, count] for (a, b), count in counter.iteritems()]
>>> final
[['block', 3, 2], ['street', 2, 4], ['lamp', 1, 2], ['industrial', 3, 3], ['park', 2, 2], ['park', 3, 1]]
请注意,您的第一个 for 循环是按二次缩放的,至于那个 while 循环,我不想考虑它,我认为也可能是二次的,但也许更糟(因为您 .pop(i)
) 但我在上面发布的解决方案是线性扩展的。所以它应该能够有效地处理更大的数据集。