key
key

Reputation: 63

python split list based on condition/if else statement

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

Answers (3)

Jean-François Fabre
Jean-François Fabre

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

PM 2Ring
PM 2Ring

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

Ayush
Ayush

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

Related Questions