如何将我的python列表转换为另一种列表格式

时间:2012-01-31 09:43:57

标签: python

我有一个包含三个这样的参数的列表: -

[(8L, 'Mail Opened', 'Saturday'), (4L, 'Mail Not Opened', 'Saturday'), (2L, 'Mail Not Opened', 'Sunday'), (8L, 'Mail Opened', 'Sunday'), (1L, 'Mail Not Opened', 'Monday'), (12L, 'Mail Opened', 'Monday'), (10L, 'Mail Opened', 'Tuesday'), (4L, 'Mail Not Opened', 'Tuesday'), (14L, 'Mail Opened', 'Wednesday'), (6L, 'Mail Not Opened', 'Wednesday'), (1L, 'Mail Not Opened', 'Thursday'), (19L, 'Mail Opened', 'Thursday'), (28L, 'Mail Opened', 'Friday'), (1L, 'Mail Opened', 'Friday')]

我可以得到这样的结果

[("Saturday",8,4)],[("Sunday",8,2)]

这里我根据DAYNAME结合了两个元组。我把“Mail Opened”值放在第一位,“Mail not open value”放在第二位。也可能存在只有一个值可能存在的情况 列表看起来像

[("Saturday",0,4)],[("Sunday",8,0)]

请帮帮我

3 个答案:

答案 0 :(得分:2)

您使用tuple作为dict,使用字典(或本例中为defaultdict)会更简单。 看看:

from collections import defaultdict

lst = [(8L, 'Mail Opened', 'Saturday'), (4L, 'Mail Not Opened', 'Saturday'), (2L, 'Mail Not Opened', 'Sunday'), (8L, 'Mail Opened', 'Sunday'), (1L, 'Mail Not Opened', 'Monday'), (1L, 'Mail Not Opened', 'Monday'), (12L, 'Mail Opened', 'Monday'), (10L, 'Mail Opened', 'Tuesday'), (4L, 'Mail Not Opened', 'Tuesday'), (14L, 'Mail Opened', 'Wednesday'), (6L, 'Mail Not Opened', 'Wednesday'), (1L, 'Mail Not Opened', 'Thursday'), (19L, 'Mail Opened', 'Thursday'), (28L, 'Mail Opened', 'Friday'), (1L, 'Mail Opened', 'Friday')]

d = {'Mail Opened': defaultdict(list), 'Mail Not Opened': defaultdict(list)}

for num,mail,day in lst:
    d[mail][day].append(num)

这将在“Mail Opend”和“Mail Not Opened”之间划分您的输出。

DAYNAME作为键

但似乎我的问题很困惑,你希望输出除以DAYNAME。

在这种情况下,通过稍微调整,我们可以恢复字典的嵌套顺序:

from collections import defaultdict

lst = [(8, 'Mail Opened', 'Saturday'), (4, 'Mail Not Opened', 'Saturday'), (2, 'Mail Not Opened', 'Sunday'), (8, 'Mail Opened', 'Sunday'), (1, 'Mail Not Opened', 'Monday'), (1, 'Mail Not Opened', 'Monday'), (12, 'Mail Opened', 'Monday'), (10, 'Mail Opened', 'Tuesday'), (4, 'Mail Not Opened', 'Tuesday'), (14, 'Mail Opened', 'Wednesday'), (6, 'Mail Not Opened', 'Wednesday'), (1, 'Mail Not Opened', 'Thursday'), (19, 'Mail Opened', 'Thursday'), (28, 'Mail Opened', 'Friday'), (1, 'Mail Opened', 'Friday')]


days = defaultdict(lambda : {'Mail Opened': [], 'Mail Not Opened': []})

for num,mail,day in lst:
    days[day][mail].append(num)

这将产生这种输出:

for k,v in days.iteritems():
    print k, v

"""
Monday {'Mail Not Opened': [1, 1], 'Mail Opened': [12]}
Tuesday {'Mail Not Opened': [4], 'Mail Opened': [10]}
Friday {'Mail Not Opened': [], 'Mail Opened': [28, 1]}
Wednesday {'Mail Not Opened': [6], 'Mail Opened': [14]}
Thursday {'Mail Not Opened': [1], 'Mail Opened': [19]}
Sunday {'Mail Not Opened': [2], 'Mail Opened': [8]}
Saturday {'Mail Not Opened': [4], 'Mail Opened': [8]}
"""

这种方法将以完全相同的方式处理每个案例,因此如果您可以重构代码,我真的建议这个。

特例:

记下您的评论我找到了一个您要为('Friday', 'Mail Opened', ..)提供两种不同输出的地方,例如:

[('Friday', 1L, 0), ('Friday', 28L, 0)]

而不是将它们链接到一起。这种特殊情况对你有意义吗?这是一个要求吗?如果答案是肯定的,请更新您的问题。

你还说你不会期望超过两个等于DAYNAME,但在你的例子中有3个Monday,其中两个看起来相似,所以也许是一个错字(如果是,请更新你的问题) 。
但如果这是一个错字,你确定双星期五入口不是拼写错误吗?

无论如何,删除“额外”Monday ,并假设你真的需要这种输出(可能是出于兼容性API原因),你能做到:

lst = [(8, 'Mail Opened', 'Saturday'), (4, 'Mail Not Opened', 'Saturday'), (2, 'Mail Not Opened', 'Sunday'), (8, 'Mail Opened', 'Sunday'), (1, 'Mail Not Opened', 'Monday'), (12, 'Mail Opened', 'Monday'), (10, 'Mail Opened', 'Tuesday'), (4, 'Mail Not Opened', 'Tuesday'), (14, 'Mail Opened', 'Wednesday'), (6, 'Mail Not Opened', 'Wednesday'), (1, 'Mail Not Opened', 'Thursday'), (19, 'Mail Opened', 'Thursday'), (28, 'Mail Opened', 'Friday'), (1, 'Mail Opened', 'Friday')]

pos = {'Mail Opened': 1, 'Mail Not Opened': 2}
results = []

for num,mail,day in lst:
    found = False
    for x in results:
        if day == x[0]:
            found = True
            if x[pos[mail]] == 0:
                x[pos[mail]] = num
            else:                   # this will handle your special case
                new = [day, 0, 0]
                new[pos[mail]] = num
                results.append(new)
            break

    if not found:
        new = [day, 0, 0]
        new[pos[mail]] = num
        results.append(new)

这将为您提供此输出:

for r in results:
    print r

"""
['Saturday', 8, 4]
['Sunday', 8, 2]
['Monday', 12, 1]
['Tuesday', 10, 4]
['Wednesday', 14, 6]
['Thursday', 19, 1]
['Friday', 28, 0]
['Friday', 1, 0]
"""

注意:

  1. 这最后一个解决方案并不关心你有多少'星期五'(或任何DAYNAME)条目。旧条目不会被覆盖,将创建一个新条目 但请注意,如果你有超过两个'星期五',你的输出将在逻辑上不一致和伪随机!这是设计失败,所以我不建议你使用最后一种方法。
  2. 您在评论中显示的错误(关于此答案和另一个答案)看起来像是在遮蔽内置list。这意味着在代码中的某些时候,您可以执行以下操作:

    list = # something
    

    请勿这样做,请使用其他名称,例如lst

答案 1 :(得分:1)

尺寸硬编码,但你做了什么

import itertools

dat = [(8L, 'Mail Opened', 'Saturday'), (4L, 'Mail Not Opened', 'Saturday'),
       (2L, 'Mail Not Opened', 'Sunday'), (8L, 'Mail Opened', 'Sunday'),
       (1L, 'Mail Not Opened', 'Monday'), (1L, 'Mail Not Opened', 'Monday'),
       (12L, 'Mail Opened', 'Monday'), (10L, 'Mail Opened', 'Tuesday'),
       (4L, 'Mail Not Opened', 'Tuesday'), (14L, 'Mail Opened', 'Wednesday'),
       (6L, 'Mail Not Opened', 'Wednesday'), (1L, 'Mail Not Opened', 'Thursday'),
       (19L, 'Mail Opened', 'Thursday'), (28L, 'Mail Opened', 'Friday'), (1L, 'Mail Opened', 'Friday')]

solution = []
dat.sort(key=lambda t: t[2])
for day, grp in itertools.groupby(dat, key=lambda t: t[2]):
    mo, mno = 0, 0
    grp = list(grp)
    if len(grp) == 1:
        if grp[0][1] == 'Mail Opened':
            solution.append((day, rec[0], 0))
        elif grp[0][1] == 'Mail Not Opened':
            solution.append((day, 0, rec[0]))
    elif len(grp) == 2:
        if grp[0][1] == grp[1][1]:
            if grp[0][1] == 'Mail Opened':
                solution.append((day, grp[0][0], 0))
                solution.append((day, grp[1][0], 0))
            elif grp[0][1] == 'Mail Not Opened':
                solution.append((day, 0, grp[0][0]))
                solution.append((day, 0, grp[1][0]))
        else:
            if grp[0][1] == 'Mail Opened':
                solution.append((day, grp[0][0], grp[1][0]))
            elif grp[1][0] == 'Mail Not Opened':
                solution.append((day, grp[1][0], grp[0][0]))
print(solution)

"""
Solution:
[('Friday', 28L, 0), ('Friday', 1L, 0), ('Saturday', 8L, 4L), 
('Tuesday', 10L, 4L), ('Wednesday', 14L, 6L)]
"""

答案 2 :(得分:0)

以下是使用单个defaultdict并在处理后将结果转换为所需表单的解决方案。

from collections import defaultdict

def convert(source):
    days = defaultdict(lambda: [0, 0])
    for item in source:
        opened = 1
        if item[1] == 'Mail Opened':
            opened = 0
        days[item[2]][opened] = item[0]
    return days.iteritems()

source = [
    (8L, 'Mail Opened', 'Saturday'),
    (4L, 'Mail Not Opened', 'Saturday'),
    (2L, 'Mail Not Opened', 'Sunday'),
    (8L, 'Mail Opened', 'Sunday'),
    (1L, 'Mail Not Opened', 'Monday'),
    (1L, 'Mail Not Opened', 'Monday'),
    (12L, 'Mail Opened', 'Monday'),
    (10L, 'Mail Opened', 'Tuesday'),
    (4L, 'Mail Not Opened', 'Tuesday'),
    (14L, 'Mail Opened', 'Wednesday'),
    (6L, 'Mail Not Opened', 'Wednesday'),
    (1L, 'Mail Not Opened', 'Thursday'),
    (19L, 'Mail Opened', 'Thursday'),
    (28L, 'Mail Opened', 'Friday'),
    (1L, 'Mail Opened', 'Friday')]

print list(convert(source))

结果:

[('Monday', [12L, 1L]),
 ('Tuesday', [10L, 4L]),
 ('Friday', [1L, 0]),
 ('Wednesday', [14L, 6L]),
 ('Thursday', [19L, 1L]), 
 ('Sunday', [8L, 2L]),
 ('Saturday', [8L, 4L])]