python中的列表操作

python中的列表操作,python,list,Python,List,我有一个包含子列表的列表。例如:([1,2],[1,56],[2787],[2,98],[3,90]),它是在运行for循环时通过向其添加值而创建的 我正在使用python,我想在每个子列表中添加第二个元素,其中第一个元素相同。在我的例子中: 我想加上2+56(都有第一个索引为1),787+98(都有第一个索引为2),并保持90不变,因为只有一个元素的第一个索引为3 我不知道该怎么做 这是我的密码: import urllib, re from itertools import groupby

我有一个包含子列表的列表。例如:(
[1,2],[1,56],[2787],[2,98],[3,90]
),它是在运行for循环时通过向其添加值而创建的

我正在使用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])
这不是一个列表。当我打印新的[0][0]时,我得到1。我希望在打印新[0][0]时获得112。追加有什么问题吗?
[334',0.5851519557155408]

这可能是itertools的工作:

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
>>> 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的排序算法足够聪明,可以利用数据中的运行,所以它可能不会——这完全取决于数据。不过,如果您的数据是高度反排序的,那么基于s
defaultdict
的解决方案可能会更好。(但忽略第一个
计数器
片段——我不知道那里发生了什么。)

关于如何创建列表的几个注意事项--有很多方法,但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]]

这很简单
dict.get(键,默认值)
返回键存在时的值,或返回默认值

totals = {}
for k,v in data:
    totals[k] = totals.get(k, 0) + v
事实上,你:

要添加每个子列表中第一个元素相同的第二个元素吗

这让我觉得你想使用dict而不是列表-dict被优化为基于第一个值检索第二个值

一些代码大致如下:

oldvalue = mydict.get(firstvalue, 0)
newvalue = oldvalue + secondvalue
mydict[firstvalue] = newvalue
可以让你边走边建立dict,或者如果这不可行,它可以让你只通过一次列表计算出总数

在解释器中快速旋转以测试这一点:

>>> l = [[1, 2], [1, 56], [2, 787], [2, 98], [3, 90]]
>>> mydict = {}
>>> for firstvalue, secondvalue in l:
...   oldvalue = mydict.get(firstvalue, 0)
...   newvalue = oldvalue + secondvalue
...   mydict[firstvalue] = newvalue
... 
>>> print mydict
{1: 58, 2: 885, 3: 90}


看起来与您想要的非常接近。

它给出了以下错误:“对于键,新列表中的值:ValueError:太多值无法解包”您在列表中的第一位代码将无法工作,因为“dict”-列表中存在键冲突。您的反例不起作用
dict
只保留每个键的最后一个值。@ghbhatt,确保列表中的所有“对”实际上都是对。其中有一个项目包含三个或更多项目。@RobWouters:是的,确实有。当我运行第1个版本时,我得到了以下错误:“print collections.Counter(dict(new_list))ValueError:dictionary update sequence元素#0的长度为3;需要2。”但当我打印len(new_list)时,它为每个元素显示2。我不明白值是3的位置。它给了我以下错误:“sums=[[key,sum(i[1]表示组中的i)]表示键,组中的键\u组]类型错误:“float”对象不可下标“@ghbhatt:请打印出您的列表;这段代码应该可以很好地工作。排序会将时间复杂度从O(n)增加到O(n log n)。@ghbhatt:这些术语与这段代码配合得很好,您缺少了一些东西。你能把x的set(tuple(map(type,x))的结果发布到你的列表中吗?“有些东西并不像你想象的那样。”沃尔夫拉姆,说得对。但这确实取决于数据;在利用半排序数据中的运行方面非常聪明。我看到的第一件事是,在
function1
中,您创建
production
new
,然后将两者都扔掉。Append可以很好地工作。您认为函数退出后,
new
会发生什么变化?您必须返回它并将其放入列表中,才能获得
new
s的列表。@ghbhatt:“new”显然不是整个列表,它只是您为每个2元素列表指定的临时名称。new[0]是第一个条目,即字符串“112”,new[0][0]是该字符串的第一个字符,即“1”。你实际上没有积累任何东西,因为正如senderle所说,你把它扔掉了。还有,为什么这段代码中有分号?@DSM:我想把docid和生产值存储在一个新列表中。我该怎么做?请帮忙。我是python新手,因此语法错误;总计=默认DICT(整数);对于数据中的k,v:totals[k]+=v
,根据对以下问题的评论,您的版本和我的修改将不起作用。@hughdbrown,您误解了这些评论。他们指的是基于
计数器的解决方案。基于
defaultdict
的解决方案是正确的。@senderle--很有趣。我原以为
计数器
只是python 2.7对collections.defaultdict(int)的专门化。@hughdbrown,是的,但是
计数器
只是以一个简单的序列计算特定键的实例。它不做任何求和之类的事情。换句话说,
计数器
要想在这里有所帮助,您必须向它传递如下列表:
[1,1,1,1,1,2,2,2,3,3,3,3,3,3,3,3…]
>>> l = [[1, 2], [1, 56], [2, 787], [2, 98], [3, 90]]
>>> mydict = {}
>>> for firstvalue, secondvalue in l:
...   oldvalue = mydict.get(firstvalue, 0)
...   newvalue = oldvalue + secondvalue
...   mydict[firstvalue] = newvalue
... 
>>> print mydict
{1: 58, 2: 885, 3: 90}