So there is a list which contains
'3,2,5,4,1','3,1,2,5,4','2,5,1,4,3'
These numbers are part of the same list, HOWEVER they are strings in a list(ie. list 1)
and from this, you say that for the "first row", 3 occurs at position 0, 2 occurs at position 1, 5 at 2 etc.
For the "second row", 3 occurs at position 0, 1 occurs at position 1, 2 occurs at position 2 etc.
I would like to create a loop or anything at all (besides using imported functions) to create a final list which looks like
0: [3, 3, 2]
1: [2, 1, 5]
2: [5, 2, 1]
3: [4, 5, 4]
4: [1, 4, 3]
Transposition of a two-dimensional list can simply be done using zip()
In [1]: l = [[3,2,5,4,1],
...: [3,1,2,5,4],
...: [2,5,1,4,3]]
In [2]: t = list(zip(*l))
In [3]: t
Out[3]: [(3, 3, 2), (2, 1, 5), (5, 2, 1), (4, 5, 4), (1, 4, 3)]
To output that in the format described above:
In [4]: for n,line in enumerate(t):
...: print("{}: {}".format(n, list(line)))
...:
0: [3, 3, 2]
1: [2, 1, 5]
2: [5, 2, 1]
3: [4, 5, 4]
4: [1, 4, 3]
Single line of code using Dictionary comprehension and List comprehension :
>>> { col:[row[col] for row in l] for col in range(len(l[0])) }
=> {0: [3, 3, 2], 1: [2, 1, 5], 2: [5, 2, 1], 3: [4, 5, 4], 4: [1, 4, 3]}
#driver values :
IN : l = [[3,2,5,4,1],
[3,1,2,5,4],
[2,5,1,4,3]]
NOTE to OP : what your output suggests is a Dictionary by looking at its structure. A list cannot be defined in the same manner.
EDIT : Since the OP's list is a list of strings, first convert that to a list of int using map and then continue as above.
>>> l = ['3,2,5,4,1', '3,1,2,5,4', '2,5,1,4,3']
>>> l = [list(map(int,s.split(','))) for s in l]
>>> l
=> [[3, 2, 5, 4, 1], [3, 1, 2, 5, 4], [2, 5, 1, 4, 3]]
Related
I am trying to create a function which can separate a list into two new lists based on a value (in this case 3.5).
The code I have tried to make so far makes a list of the first values in the main list (the ones I want to compare). This list is [1,1,3,1,4,4,5,1] I now want to create two lists. This would be [1,1,3,1,1] and [4,4,5]. However, I cannot use > to compare the different values in the list and am unsure how to do so.
As I said above, I'm confused about what your code is trying to do, but you can split a list like this.
my_list=[1,1,3,1,4,4,5,1]
my_val=3.5 #value to split on
list1=[x for x in my_list if x>my_val]
list2=[x for x in my_list if x<my_val]
EDIT
To make this work for a list of tuples, based on their first value, you can do the same but with a slight modification
my_list = [(1, 4, 3, 0),
(1, 7, 6, 0),
(3, 8, 7, 0),
(1, 1, 9, 0),
(4, 1, 1, 0),
(4, 3, 8, 1),
(5, 4, 2, 1),
(1, 7, 7, 1)]
list1=[x for x in my_list if x[0]>my_val]
list2=[x for x in my_list if x[0]<my_val]
The itertools module documentation provides a series of recipes for common tasks. One of them is a partition function.
from itertools import tee, filterfalse
def partition(pred, iterable):
"Use a predicate to partition entries into false entries and true entries"
# partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9
t1, t2 = tee(iterable)
return filterfalse(pred, t1), filter(pred, t2)
my_list=[1,1,3,1,4,4,5,1]
t1, t2 = partition(lambda x: x > 3.5, my_list)
list1 = list(t1) # [1, 1, 3, 1, 1]
list2 = list(t2) # [4, 4, 5]
You can have a function to split your list for a value.
def split_list(val, _list):
list1 = []
list2 = []
for _x in _list:
(list1 if _x <= val else list2).append(_x)
return list1, list2
# Your example
print(split_list(3.5, [1, 1, 3, 1, 4, 4, 5, 1]))
#brings output
#([1, 1, 3, 1, 1], [4, 4, 5])
And call it repeated for a data set as you said
# For a data set like yours
my_list = [(1, 4, 3, 0),
(1, 7, 6, 0),
(3, 8, 7, 0),
(1, 1, 9, 0),
(4, 1, 1, 0),
(4, 3, 8, 1),
(5, 4, 2, 1),
(1, 7, 7, 1)]
my_list_1 = []
my_list_2 = []
for x in my_list:
g, le = split_list(3.5, x)
my_list_1.append(g)
my_list_2.append(le)
print(my_list_1)
print(my_list_2)
# Separates the list to
[[1, 3, 0], [1, 0], [3, 0], [1, 1, 0], [1, 1, 0], [3, 1], [2, 1], [1, 1]]
[[4], [7, 6], [8, 7], [9], [4], [4, 8], [5, 4], [7, 7]]
This question already has answers here:
Split List By Value and Keep Separators
(8 answers)
Closed 1 year ago.
Is there an easy way to split the list l below into 3 list. I want to cut the list when the sequence starts over. So every list should start with 1.
l= [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4]
l1 = [1, 2, 3,4, 5]
l2=[1,2,3,4]
l3=[1,2,3,4]
My original thought was to look at the lead value and implement a condition inside a for loop that would cut the list when x.lead < x. But how do I use lead and lag when using lists in python?
NumPy solution
import numpy as np
l = [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4]
parts = [list(i) for i in np.split(l,np.flatnonzero(np.diff(l)-1)+1)]
print(parts)
output
[[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4]]
Explanation: I first find differences between adjacent elements using numpy.diff, then subtract 1 to be able to use numpy.flatnonzero to find where difference is other than 1, add 1 (note that numpy.diff output length is input length minus 1) to get indices for use in numpy.split, eventually convert it to list, as otherwise you would end with numpy.arrays
What about this:
l = [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4]
one_indices = [i for i, e in enumerate(l) if e == 1]
slices = []
for count, item in enumerate(one_indices):
if count == len(one_indices) - 1:
slices.append((item, None))
else:
slices.append((item, one_indices[count + 1]))
sequences = [l[x[0] : x[1]] for x in slices]
print(sequences)
Out:
[[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4]]
Another way without numpy,
l= [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4]
start = 0
newlist = []
for i,v in enumerate(l):
if i!=0 and v==1:
newlist.append(l[start:i])
start = i
newlist.append(l[start:i+1])
print(newlist)
Working Demo: https://rextester.com/RYCV85570
I want to weave two lists and output all the possible results.
For example,
input: two lists l1 = [1, 2], l2 = [3, 4]
output: [1, 2, 3, 4], [1, 3, 2, 4], [1, 3, 4, 2], [3, 1, 2, 4], [3, 1, 4, 2], [3, 4, 1, 2]
Note: I need to keep the order in each list (e.g. 1 is always before 2, and 3 is always before 4)
The way I am solving this is by removing the head from one list, recursing, and then doing the same thing with the other list. The code is below:
all_possibles = []
def weaveLists(first, second, added):
if len(first) == 0 or len(second) == 0:
res = added[:]
res += first[:]
res += second[:]
all_possibles.append(res)
return
cur1 = first[0]
added.append(cur1)
first = first[1:]
weaveLists(first, second, added)
added = added[:-1]
first = [cur1] + first
cur2 = second[0]
added.append(cur2)
second = second[1:]
weaveLists(first, second, added)
added = added[:-1]
second = [cur2] + second
weaveLists([1, 2], [3, 4], [])
print(all_possibles)
The result I got is:
[[1, 2, 3, 4], [1, 3, 2, 4], [1, 3, 4, 2], [1, 3, 1, 2, 4], [1, 3, 1, 4, 2], [1, 3, 1, 4, 1, 2]]
I couldn't figure out why for the last three lists, the heading 1 from the first list is not removed.
Can anyone help? Thanks!
The reason you get those unexpected results is that you mutate added at this place:
added.append(cur1)
...this will affect the caller's added list (unintentionally). While the "undo" operation is not mutating the list:
added = added[:-1]
This creates a new list, and therefore this "undo" action does not roll back the change in the list of the caller.
The easy fix is to replace the call to append with:
added = added + [cur1]
And the same should happen in the second block.
It is easier if you pass the new values for the recursive call on-the-fly, and replace those two code blocks with just:
weaveLists(first[1:], second, added + [first[0]])
weaveLists(first, second[1:], added + [second[0]])
Here is another way to do it: we generate the possible indices of the items of the first list inside the weaved list, and fill the list accordingly.
We can generate the indices with itertools.combinations: it's the combinations of the indices of the weaved list, taking len(first_list) of them each time.
from itertools import combinations
def weave(l1, l2):
total_length = len(l1) + len(l2)
# indices at which to put items from l1 in the weaved output
for indices in combinations(range(total_length), r=len(l1)):
out = []
it1 = iter(l1)
it2 = iter(l2)
for i in range(total_length):
if i in indices:
out.append(next(it1))
else:
out.append(next(it2))
yield out
Sample run:
l1 = [1, 2]
l2 = [3, 4]
for w in weave(l1, l2):
print(w)
[1, 2, 3, 4]
[1, 3, 2, 4]
[1, 3, 4, 2]
[3, 1, 2, 4]
[3, 1, 4, 2]
[3, 4, 1, 2]
Another sample run with a longer list:
l1 = [1, 2]
l2 = [3, 4, 5]
for w in weave(l1, l2):
print(w)
[1, 2, 3, 4, 5]
[1, 3, 2, 4, 5]
[1, 3, 4, 2, 5]
[1, 3, 4, 5, 2]
[3, 1, 2, 4, 5]
[3, 1, 4, 2, 5]
[3, 1, 4, 5, 2]
[3, 4, 1, 2, 5]
[3, 4, 1, 5, 2]
[3, 4, 5, 1, 2]
I have a list such as this:
original = [1, 2, 3, 4]
and another one of which I will find the sublists:
queries = [1, 4, 1, 5, 2, 3, 2, 1]
I want all the sublists which include only one instance of the original list. So in this example, I would get:
sublists = [ [1, 2, 3, 4], [1, 2], [1] ]
and my original would be left with:
original = [5]
How would I achieve this? Thank you
One slightly indirect approach would be to utilise the collections.Counter library object:
from collections import Counter
from itertools import zip_longest, repeat
original = [1, 2, 3, 4]
query = [1, 4, 1, 5, 2, 3, 2, 1]
cnts = Counter(query)
# cnts: Counter({1: 3, 2: 2, 4: 1, 5: 1, 3: 1})
sublists = zip_longest(*map(repeat, original, map(cnts.pop, original)))
# this creates the approprate number of copies of 1, 2, 3, 4 and (via
# zip_longest) shuffles them into lists with max one occurrence each
# sublists are padded with None's -- [(1, 2, 3, 4), (1, 2, None, None), (1, None, None, None)]
sublists = list(map(list, map(filter, repeat(bool), sublists)))
# None's are removed -- [[1, 2, 3, 4], [1, 2], [1]]
leftovers = list(filter(cnts.__contains__, query))
# [5]
I have a list [[1, 2, 7], [1, 2, 3], [1, 2, 3, 7], [1, 2, 3, 5, 6, 7]] and I need [1,2,3,7] as final result (this is kind of reverse engineering). One logic is to check intersections -
while(i<dlistlen):
j=i+1
while(j<dlistlen):
il = dlist1[i]
jl = dlist1[j]
tmp = list(set(il) & set(jl))
print tmp
#print i,j
j=j+1
i=i+1
this is giving me output :
[1, 2]
[1, 2, 7]
[1, 2, 7]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3, 7]
[]
Looks like I am close to getting [1,2,3,7] as my final answer, but can't figure out how. Please note, in the very first list (([[1, 2, 7], [1, 2, 3], [1, 2, 3, 7], [1, 2, 3, 5, 6, 7]] )) there may be more items leading to one more final answer besides [1,2,3,4]. But as of now, I need to extract only [1,2,3,7] .
Please note, this is not kind of homework, I am creating own clustering algorithm that fits my need.
You can use the Counter class to keep track of how often elements appear.
>>> from itertools import chain
>>> from collections import Counter
>>> l = [[1, 2, 7], [1, 2, 3], [1, 2, 3, 7], [1, 2, 3, 5, 6, 7]]
>>> #use chain(*l) to flatten the lists into a single list
>>> c = Counter(chain(*l))
>>> print c
Counter({1: 4, 2: 4, 3: 3, 7: 3, 5: 1, 6: 1})
>>> #sort keys in order of descending frequency
>>> sortedValues = sorted(c.keys(), key=lambda x: c[x], reverse=True)
>>> #show the four most common values
>>> print sortedValues[:4]
[1, 2, 3, 7]
>>> #alternatively, show the values that appear in more than 50% of all lists
>>> print [value for value, freq in c.iteritems() if float(freq) / len(l) > 0.50]
[1, 2, 3, 7]
It looks like you're trying to find the largest intersection of two list elements. This will do that:
from itertools import combinations
# convert all list elements to sets for speed
dlist = [set(x) for x in dlist]
intersections = (x & y for x, y in combinations(dlist, 2))
longest_intersection = max(intersections, key=len)