Reputation: 111
Given the following list:
lst = [[3,5],[3,10],[3,15],[3,102],[5,21],[5,23],[5,50]]
I want to obtain the following
[[3,5,10,15,102], [5,21,23,50]]
Note that the list is sorted in ascending order based on the value of the first element.
What would be the most efficient way of doing this? This is what I was thinking:
Step 1: Create a list with unique first elements. (i.e. 3 and 5 in this case)
first_elements = [] #initialize empty list to which we will append all first elements
for i in range(len(lst)):
first_elements.append(lst[i][0])
first_elements = list(set(first_elements)) #Filter out the unique first elements
first_elements = [3,5]
Step 2: Filter lst based on the first element. Append these to a new list.
new_merged_list = [] # create new list to append to
for i in range(len(first_elements)):
first_element_to_filter_by = first_elements[i]
filtered_2d_list = [i for i in lst if i[0] == first_element_to_filter_by]
new_merged_list.append([first_element_to_filter_by])
for j in range(len(filtered_2d_list)):
(new_merged_list[i]).append(filtered_2d_list[j][1])
This gives me the correct answer, as shown below.
new_merged_list = [[3, 5, 10, 15, 102], [5, 21, 23, 50]]
My question - is there a more efficient way to do this? I don't know how well this would scale to a list that is (for instance) 100000 x 2.
Appreciate the help!
Upvotes: 2
Views: 524
Reputation: 3687
One line:
a = np.array([[0, 0], [0, 3], [0, 4], [1, 1], [2, 2], [3, 0], [3, 3], [3, 4], [4, 0], [4, 3], [4, 4]])
result = [[i]+a[a[:, 0] == i, 1].tolist() for i in np.unique(a[:, 0])]
print(result)
Upvotes: 0
Reputation: 20669
You can use defaultdict
here. This will work even if your lst
is not sorted.
from collections import defaultdict
new = defaultdict(list)
lst = [[3, 5], [3, 10], [3, 15], [3, 102], [5, 21], [5, 23], [5, 50]]
for k,v in lst:
new[k].append(v)
new = [[k]+v for k,v in new.items()]
# [[3, 5, 10, 15, 102], [5, 21, 23, 50]]
# Or
new = [[k,*v] for k,v in new.items()]
# [[3, 5, 10, 15, 102], [5, 21, 23, 50]]
Upvotes: 10
Reputation: 1504
In one pass.
lst = [[3,5],[3,10],[3,15],[3,102],[5,21],[5,23],[5,50]]
current = None
ret = []
for i in lst:
if i[0] == current:
ret[-1].append(i[1])
else:
current = i[0]
ret.append([current])
ret[-1].append(i[1])
# [[3, 5, 10, 15, 102], [5, 21, 23, 50]]
Upvotes: 2
Reputation: 686
# seems to work - assuming the initial sorting as stated
result = []
prv_first = None
for sub_lst in lst:
first = sub_lst[0]
if first != prv_first:
prv_first = first
cur_list = [] + sub_lst
result.append(cur_list)
else:
cur_list.extend(sub_lst[1:])
Upvotes: 2
Reputation: 2517
You could do something like this (without importing a module)
first_elements = list(set([item[0] for item in lst]))
result = [[elem] for elem in first_elems]
for sublist in lst:
result[first_elems.index(sublist[0])].append(sublist[1])
Upvotes: 2