Reputation: 51
I have a list of tuples as shown below. The tuples in the lists are dynamically stored. Let's say each tuple can have 6 elements or 20 elements. This count is dynamic.
a = [('Index','col1','col2','col3','col4','col5'),('1','2','4','6','78','9'),('3','6','8','9','2','1')]
I want to split first 3 elements from each tuple in a list to another list(like below).
b = [('Index','col1','col2'),('1','2','4'),('3','6','8')]
c = [('col3','col4','col5'),('6','78','9'),('9','2','1')]
Example2:
tup=[(7,6,8,19,2,4,13,1,10,25,11,34),(1,2,3,4,5,6,7,8,9,10,11,12),(3,5,6,7,89,0,1,3,4,5,6,7)]
Output should be like this-
[(7,6,8),(1,2,3)(3,5,6)]
[(19,2,4),(4,5,6),(7,89,0)]
[(13,1,10),(7,8,9),(1,3,4)]
[(25,11,34),(10,11,12),(5,6,7)]
Any suggestions on how this can be achieved in python?
Upvotes: 1
Views: 962
Reputation: 17156
One liner that handles dynamic lists and different sizes.
def split_by(lst, size=3):
return [[t[ind:ind+size] for t in a] for ind in range(0, min(map(len, a)), size)]
print(split_by(a))
Output
[ [('Index', 'col1', 'col2'), ('1', '2', '4'), ('3', '6', '8')],
[('col3', 'col4', 'col5'), ('6', '78', '9'), ('9', '2', '1')]]
Upvotes: 0
Reputation: 1116
My solution:
def split_by(tuples, size=3):
lens = [len(t) for t in tuples]
n = min(lens)
cnt = 0
while cnt < n:
result = [t[cnt:cnt+size] for t in tuples]
yield result
cnt += size
Upvotes: 1
Reputation: 1047
A more flexible way that would work if the data size change
a = [('Index','col1','col2','col3','col4','col5'),('1','2','4','6','78','9'),('3','6','8','9','2','1')]
res = [[a[0][c:c+3], a[1][c:c+3], a[2][c:c+3]] for c in range(0,len(a[0]), 3)]
print(*res)
# [('Index', 'col1', 'col2'), ('1', '2', '4'), ('3', '6', '8')] [('col3', 'col4', 'col5'), ('6', '78', '9'), ('9', '2', '1')]
Solution 2: Taking into account different tuple sizes, so only iterate on multiple of 3 based on the shortest tuple as @Diego Palacios mentioned ;)
a = [('Index','col1','col2','col3','col4','col5','Extra'),('1','2','4','6','78','9', 'Extra'),('3','6','8','9','2','1')]
res = [[a[0][c:c+3], a[1][c:c+3], a[2][c:c+3]] for c in range(0,min(len(a[0]),len(a[1]),len(a[2]))//3*3, 3)]
print(*res)
Upvotes: 0
Reputation: 7204
You can use pandas to do this as well:
# pd.DataFrame(a).T.groupby(np.arange(len(pd.DataFrame(a).T))//3).agg(list).to_numpy().tolist()
# [[['Index', 'col1', 'col2'], ['1', '2', '4'], ['3', '6', '8']],
# [['col3', 'col4', 'col5'], ['6', '78', '9'], ['9', '2', '1']]]
2nd Example:
tup=[(7,6,8,19,2,4,13,1,10,25,11,34),(1,2,3,4,5,6,7,8,9,10,11,12),(3,5,6,7,89,0,1,3,4,5,6,7)]
pd.DataFrame(tup).T.groupby(np.arange(len(pd.DataFrame(tup).T))//3).agg(list).to_numpy().tolist()
output:
[[[7, 6, 8], [1, 2, 3], [3, 5, 6]],
[[19, 2, 4], [4, 5, 6], [7, 89, 0]],
[[13, 1, 10], [7, 8, 9], [1, 3, 4]],
[[25, 11, 34], [10, 11, 12], [5, 6, 7]]]
Upvotes: 0
Reputation: 1144
You can use list comprehension and index slicing to get the job done:
if len(a[0]) > 3:
b = [x[:3] for x in a]
c = [x[3:] for x in a]
It may not be the fastest code, but it is very clear and simple.
Upvotes: 0