Reputation: 63
I'm trying to split a list into two lists. Here's the list:
L = [3.5, 1 ,7, 2 ,4.5, 1, 6, 2, 4.8, 2 ,3.1,1, 9, 2]
If I want to split the list based on the bold number (1 or 2), which are always the even number (2x) in the position, so the numbers before 1 go to one list, and the numbers before 2 go to another list:
l1 = [3.5, 4.5, 3.1] #bold number = 1
l2 = [7, 6, 4.8, 9] #bold number = 2
Also, the question may be extend when there are i+1
bold number and thus needs to be split to i+1
list.
How should I use if
-else
statements for list?
Upvotes: 3
Views: 3649
Reputation: 140305
Do that using ternary in a step 2 loop which dispatches the previous element in the relevant list (I took a shortcut: if value is 1
, it's l1
else it's l2
, so it's rather fragile):
l=[3.5, 1 ,7, 2 ,4.5, 1, 6, 2, 4.8, 2 ,3.1,1, 9, 2]
l1,l2 = [],[]
for i in range(1,len(l),2):
(l1 if l[i]==1 else l2).append(l[i-1])
print(l1,l2)
yields:
[3.5, 4.5, 3.1] [7, 6, 4.8, 9]
General case: create a list of lists according to the maximum index, and dispatch the value according to the index in a loop (l[i]-1
is the 0-starting index and l[i]
is the value to insert)
lists = [[] for _ in range(max(l[1::2]))]
for i in range(1,len(l),2):
lists[l[i]-1].append(l[i-1])
print(lists)
result:
[[3.5, 4.5, 3.1], [7, 6, 4.8, 9]]
more "pythonic" for the last part using itertools.islice
instead of playing with indexes:
import itertools
for i,v in zip(itertools.islice(l,1,len(l),2),itertools.islice(l,0,len(l),2)):
lists[i-1].append(v)
Upvotes: 5
Reputation: 55499
You can use a dictionary to hold the new lists, using the category number as the dictionary key. We use a defaultdict to simplify creating the lists in the dictionary.
from collections import defaultdict
lst = [3.5, 1 ,7, 2, 4.5, 1, 6, 2, 4.8, 2, 3.1, 1, 9, 2]
# Separate data into different lists based on following number
d = defaultdict(list)
it = iter(lst)
for v, k in zip(it, it):
d[k].append(v)
# Display lists
for k in sorted(d.keys()):
print(k, d[k])
output
1 [3.5, 4.5, 3.1]
2 [7, 6, 4.8, 9]
This code copes with any number of categories.
As Jean-François Fabre mentions in the comments there's a slightly more efficient way to do the printing in sorted order.
from collections import defaultdict
lst = [3.5, 1 ,7, 2, 4.5, 3, 6, 2, 4.8, 3, 3.1, 1, 9, 2]
# Separate data into different lists based on following number
d = defaultdict(list)
it = iter(lst)
for v, k in zip(it, it):
d[k].append(v)
# Display lists
for k, v in sorted(d.items()):
print(k, v)
output
1 [3.5, 3.1]
2 [7, 6, 9]
3 [4.5, 4.8]
The heart of this algorithm is
it = iter(lst)
for v, k in zip(it, it):
it = iter(lst)
creates an iterator object from the list. We then pass two copies of that iterator to zip
.
Looping over zip
yields tuples containing the successive items from each of the arguments you feed it. In other words, if you do zip(a, b, c)
you get the first elements of each of a
, b
, c
, then you get their 2nd elements, etc.
But here we've passed zip
two references to the it
iterator. So when zip
reads the next items from each of the two it
s its really working its way through the pairs of items in lst
. Thus on each loop of the for
loop we get successive pairs of items from lst
.
Upvotes: 5
Reputation: 3965
not the cleanest attempt, but here you go
>>> L=[3.5, 1 ,7, 2 ,4.5, 1, 6, 2, 4.8, 2 ,3.1,1, 9, 2]
>>> o=zip(L, L[1:])[::2]
>>> o
[(3.5, 1), (7, 2), (4.5, 1), (6, 2), (4.8, 2), (3.1, 1), (9, 2)]
>>> map(lambda x: x[0], filter(lambda x: x[1]%2==0, o))
[7, 6, 4.8, 9]
>>> map(lambda x: x[0], filter(lambda x: x[1]%2!=0, o))
[3.5, 4.5, 3.1]
Upvotes: 0