简体   繁体   English

根据列表中的字符串使用元组创建新列表

[英]Making a new list with tuples based on strings in the list

L = ["5", "0 1", "0 2", "1 3", "2 3", "2 4", "3 4"]

Each number represents a person. 每个数字代表一个人。 So, there are five people from 0 to 4 in the list. 因此,列表中有5个人,从0到4。 L[0] always shows how many people are in the list. L[0]始终显示列表中有多少人。

L1 = [(0,[1,2]), (1, [3]), (2, [3,4]), (3, [4])] 

The person "0" is paired with 1 and 2 . "0"12配对。 So, it has a list of 1, 2 in a tuple. 因此,它在一个元组中具有1, 2的列表。 My approach to get the result above is to compare the first character in L[1] to the end of the list. 我获得以上结果的方法是将L[1]的第一个字符与列表的末尾进行比较。 If the first letter in L[1] matches with the first letter in L[2] , it bundles the second letter in L[2] with the second letter in L[1] . 如果L[1]中的第一个字母与L[2]的第一个字母匹配,则会将L[2]中的第二个字母与L[1]的第二个字母捆绑在一起。 Finally, the new list is paired with 0 in a tuple. 最后,新列表在元组中与0配对。 By the way, I cannot come up with such thing that can check the first letter in strings. 顺便说一句,我无法提出可以检查字符串中第一个字母的东西。 I am not sure if this approach is right or not. 我不确定这种方法是否正确。

I am struggling to make such list L1 above. 我努力在上面列出这样的清单L1 Could anyone let me know if my approach to this question is right? 谁能告诉我我对这个问题的解决方法是否正确? If it is wrong, please briefly give me a hint to solve this. 如果有误,请简要提示我解决此问题。

Using list comprehension 使用列表理解

Created a list in the required range, considering L[0] 考虑到L[0] ,在所需范围内创建了一个列表

Checks for matches between the element and the other items using startswith 使用startswith检查元素和其他项目之间的匹配

L = ["5", "0 1", "0 2", "1 3", "2 3", "2 4", "3 4"]
L1 = [(0,[1,2]), (1, [3]), (2, [3,4]), (3, [4])]     # required list

L2 = [ (i, [ int(x[-1]) for x in L if str(x).startswith(str(i)) ]) for i in range(int(L[0])-1) ]

Output 产量

[(0, [1, 2]), (1, [3]), (2, [3, 4]), (3, [4])]
[(0, [1, 2]), (1, [3]), (2, [3, 4]), (3, [4])]

Probably the best thing is to first use a defaultdict : 最好的办法是先使用defaultdict

from collections import defaultdict
from itertools import islice

result = defaultdict(list)

for li in islice(L,1,None):
    h, *others = map(int,li.split())
    for other in others:
        result[h].append(other)

Or a version that works for : 或适用于

from collections import defaultdict
from itertools import islice

result = defaultdict(list)

for li in islice(L,1,None):
    data = map(int,li.split())
    h = data[0]
    for other in data[1:]:
        result[h].append(other)

and then we obtain the items of that dictionary: 然后我们获得该词典的items

L1 = list(result.items())

This produces: 这将产生:

>>> L1
[(0, [1, 2]), (1, [3]), (2, [3, 4]), (3, [4])]

Note that in this case the items are not ordered: since a dictionary in Python usually has no order (the latest implementations in CPython have, but this is seen as an implementation detail). 请注意,在这种情况下,项目没有顺序:因为Python中的字典通常没有顺序(CPython中的最新实现是有顺序的,但这被视为实现细节)。

But converting the dictionary back into a list is not logical, since the advantage of a dictionary is a fast lookup (in O(1) , constant time). 但是将字典转换回列表是不合逻辑的,因为字典的优点是可以快速查找(在O(1)中为常数时间)。

We can make the last part more elegant by writing: 我们可以通过编写以下内容使最后一部分更优雅:

from collections import defaultdict

result = defaultdict(list)

for li in islice(L,1,None):
    h, *others = map(int,li.split())
    result[h] += others

Instead of list, go with dict and use this pattern without importing any external module. 而不是列表,请使用dict并使用此模式,而无需导入任何外部模块。

L = ["5", "0 1", "0 2", "1 3", "2 3", "2 4", "3 4"]

final_dict={}
new=[]
for item in L:
    if not len(item)<2:
        if int(item[0]) not in final_dict:
            final_dict[int(item[0])]=[int(item[2])]
        else:
            final_dict[int(item[0])].append(int(item[2]))

print(final_dict)

output: 输出:

{0: [1, 2], 1: [3], 2: [3, 4], 3: [4]}

or if you want the result in the list then add this line end of above code: 或者,如果您希望结果在列表中,则在上面的代码中添加以下行:

print([(key,value) for key,value in final_dict.items()])

output: 输出:

[(0, [1, 2]), (1, [3]), (2, [3, 4]), (3, [4])]

I would suggest you use a form of dictionary for easier processing of the data later on. 我建议您使用dictionary的形式,以便以后更轻松地处理数据。 So here, defualtdict would be best utilized. 因此,这里最好使用defualtdict

>>> from collections import defaultdict
>>> L = ["5", "0 1", "0 2", "1 3", "2 3", "2 4", "3 4"]
>>> n  = int(L.pop(0))                                    #number of people

>>> d = defaultdict(list)
>>> for ele in L: 
        x, y  = map(int, ele.split()) 
        d[x].append(y)    

>>> d
=> defaultdict(<class 'list'>, {0: [1, 2], 1: [3], 2: [3, 4], 3: [4]})

If neccessary to have that list format, use dict.items() and type cast it to list 如果需要具有该list格式,请使用dict.items()并键入将其dict.items()list

>>> l1 = list(d.items())
>>> l1
=> [(0, [1, 2]), (1, [3]), (2, [3, 4]), (3, [4])]

Here is an itertools.groupy solution. 这是一个itertools.groupy解决方案。 (The commented out line also considers reverse pairs.) (注释行还考虑反向对。)

import itertools as it
import operator as op

def L1(L):
    # split pairs
    L = [p.split() for p in L[1:]]
    # convert to int
    L = [(int(P1), int(P2)) for P1, P2 in L]
    LL = sorted(L)
#    # add reversed and sort
#    LL = sorted(L + [P[::-1] for P in L])
    # group by first element
    res = it.groupby(LL, op.itemgetter(0))
    # make proper lists
    return [(k, [P[1] for P in v]) for k, v in res]

Output (for the example L ): 输出(例如L ):

[(0, [1, 2]), (1, [3]), (2, [3, 4]), (3, [4])]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM