简体   繁体   中英

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. L[0] always shows how many people are in the list.

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

The person "0" is paired with 1 and 2 . So, it has a list of 1, 2 in a tuple. My approach to get the result above is to compare the first character in L[1] to the end of the list. 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] . Finally, the new list is paired with 0 in a tuple. 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. 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]

Checks for matches between the element and the other items using 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 :

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:

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).

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).

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.

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. So here, defualtdict would be best utilized.

>>> 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

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

Here is an itertools.groupy solution. (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 ):

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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