Python中的列表操作

3 投票
4 回答
1205 浏览
提问于 2025-04-17 12:21

我有一个包含子列表的列表。例如:([1, 2], [1, 56], [2, 787], [2, 98], [3, 90]),这个列表是在一个循环中通过添加值创建的。

我在用Python编程,我想把每个子列表中第一个元素相同的第二个元素加起来。在我的例子中:我想把2和56加起来(它们的第一个元素都是1),把787和98加起来(它们的第一个元素都是2),而90保持不变,因为只有一个元素的第一个元素是3。

我不太确定该怎么做。

这是我的代码:

import urllib, re
from itertools import groupby
import collections
import itertools, operator
text = urllib.urlopen("some html page").read() 
data = re.compile(r'.*?<BODY>(.*?)<HR>', re.DOTALL).match(text).group(1)// storing contents from the BODY tag
values = [line.split() for line in data.splitlines()] //List with the BODY data
/* values contain elements like [[65, 67], [112, 123, 12], [387, 198, 09]]
   it contains elements with length 2 and three. 
   i am just concerned with elements with length 3
   in the for loop, i am doing this, and passing it to 2 functions.*/

def function1 (docid, doclen, tf):
    new=[];
    avgdoclen = 288;
    tf = float(x[2]);
    doclen = float(x[1]);
    answer1 = tf / (tf + 0.5 + (1.5*doclen/avgdoclen));
    q = function2(docid, doclen, tf)
    production = answer1 * q //this is the production of 
    new.append(docid) // i want to add all the production values where docid are same.
    new.append(production)
    return answer1

def function2 (docid, doclen, tf):
    avgdoclen = 288;
    querylen = 12;
    tf= float(x[2]);
    answer2 = tf/(tf + 0.5 + (1.5*querylen/avgdoclen));
    return answer2

for x in values:
    if len(x)==3:
        okapi_doc(x[0], x[1], x[2])
        okapi_query(x[0], x[1], x[2])

我想把所有相同docid的生产值加起来。现在当我打印new时,得到的输出是:

['112', 0.3559469323909391]
['150', 0.31715060007742935]
['158', 0.122025819265144]
['176', 0.3862207694241891]
['188', 0.5057900225015092]
['236', 0.12628982528263102]
['251', 0.12166336633663369]

这不是一个列表。当我打印new[0][0]时,我得到1。我想要的是112,当我打印new[0][0]时。append是不是有什么问题?

['334', 0.5851519557155408]

4 个回答

2

这很简单。dict.get(key, default) 这个方法会返回指定的键对应的值,如果这个键不存在,就会返回一个默认值。

totals = {}
for k,v in data:
    totals[k] = totals.get(k, 0) + v
2

这可能是用 itertools 来解决的问题:

>>> import itertools, operator
>>> l = sorted([[1, 2], [1, 56], [2, 787], [2, 98], [3, 90]])
>>> keys_groups = itertools.groupby(l, key=operator.itemgetter(0))
>>> sums = [[key, sum(i[1] for i in group)] for key, group in keys_groups]
>>> sums
[[1, 58], [2, 885], [3, 90]]

注意,要让 groupby 正常工作,列表里的项目必须按照给定的关键字排序。在这个例子中,因为关键字是每对中的第一个项目,所以我不需要排序,但如果你想要一个更通用的解决方案,应该使用 key 参数来对列表进行排序。

>>> l2 = [[787, 2], [98, 2], [90, 3], [2, 1], [56, 1]]
>>> l2.sort(key=operator.itemgetter(1))
>>> l2
[[2, 1], [56, 1], [787, 2], [98, 2], [90, 3]]
>>> keys_groups = itertools.groupby(l2, key=operator.itemgetter(1))
>>> sums = [[key, sum(i[0] for i in group)] for key, group in keys_groups]
>>> sums
[[1, 58], [2, 885], [3, 90]]

这个方法在你提供的数据上运行得很好。我稍微修改了一下,让这个例子看起来更真实。

>>> l = [['112', 0.3559469323909391], ['150', 0.31715060007742935], 
         ['158',0.122025819265144], ['176', 0.3862207694241891],
         ['188', 0.5057900225015092], ['377', 0.12628982528263102], 
         ['251', 0.12166336633663369], ['334', 0.5851519557155408], 
         ['334', 0.14663484486873507], ['112', 0.2345038167938931], 
         ['377', 0.10694516971279373], ['112', 0.28981132075471694]]
>>> l.sort(key=operator.itemgetter(0))
>>> keys_groups = itertools.groupby(l, key=operator.itemgetter(0))
>>> sums = [[key, sum(i[1] for i in group)] for key, group in keys_groups]
>>> sums
[['112', 0.88026206993954914], ['150', 0.31715060007742935], 
 ['158', 0.122025819265144], ['176', 0.38622076942418909], 
 ['188', 0.50579002250150917], ['251', 0.12166336633663369], 
 ['334', 0.73178680058427581], ['377', 0.23323499499542477]]

注意,正如 WolframH 指出的,排序通常会增加时间复杂度;不过 Python 的排序算法很聪明,可以利用数据中的顺序,所以可能不会增加复杂度——这完全取决于数据本身。不过,如果你的数据是高度反向排序的,Winston Ewert 提出的基于 defaultdict 的解决方案可能会更好。(不过忽略那个第一个 Counter 的代码片段——我对那部分不太了解。)

关于如何创建列表,有很多方法,但在 Python 中有两种基本的方法——第一种是列表推导:

>>> def simple_function(x):
...     return [x, x ** 2]
... 
>>> in_data = range(10)
>>> out_data = [simple_function(x) for x in in_data]
>>> out_data
[[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]

第二种是使用 for 循环:

>>> out_data = []
>>> for x in in_data:
...     out_data.append(simple_function(x))
... 
>>> out_data
[[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]
1

在编程中,有时候我们需要处理一些数据,比如从一个地方获取数据,然后在另一个地方使用这些数据。这个过程就像是把水从一个桶倒到另一个桶一样。

有些时候,我们会遇到一些问题,比如数据的格式不对,或者数据的类型不匹配。这就像是你想把牛奶倒进一个只适合倒水的杯子里,这样就会出问题。

为了避免这些问题,我们需要确保在处理数据之前,先检查一下数据的类型和格式。这就像是在倒水之前,先确认一下桶是不是干净的,能不能用。

总之,处理数据的时候,保持谨慎,确保每一步都是正确的,这样才能顺利完成任务。

import collections
result = collections.defaultdict(int) # works like a dictionary
# but all keys have a default value of zero
for key, value in mylist:
    result[key] += value 

print result

撰写回答