I'm having trouble wrapping my head around dealing with lists within lists in python (I am rather new at programming).
Now how would I access each nested list position and then manipulate the position of the nested list's values to, for example, change their order while maintaining the position of the nested list in the main list.
For example:
if I wanted to go from:
aList = [
[1,2,3,4,3,2],
[2,3,4,5,4,3],
[2,1,2,3,4,3]
]
to here:
new_aList = [
[2,3,4,3,2,1],
[3,4,5,4,3,2],
[3,4,3,2,1,2]
]
I get how to access each list, but I'm experiencing a block as to how I would change the position of the values of the nested lists.
Thanks for any help!
Use a list comprehension to get the new elements, and optionally slice-assign to replace the existing elements in the list.
new_aList = [list(reversed(x)) for x in aList]
aList[:] = [list(reversed(x)) for x in aList]
You could reverse each item like this
>>> aList = [
... [1,2,3,4,3,2],
... [2,3,4,5,4,3],
... [2,1,2,3,4,3]
... ]
>>> aList[0].reverse()
>>> aList[1].reverse()
>>> aList[2].reverse()
>>> aList
[[2, 3, 4, 3, 2, 1], [3, 4, 5, 4, 3, 2], [3, 4, 3, 2, 1, 2]]
But in general it's better to use a loop since aList could have lots of items
>>> aList = [
... [1,2,3,4,3,2],
... [2,3,4,5,4,3],
... [2,1,2,3,4,3]
... ]
>>> for item in aList:
... item.reverse()
...
>>> aList
[[2, 3, 4, 3, 2, 1], [3, 4, 5, 4, 3, 2], [3, 4, 3, 2, 1, 2]]
Both of those methods will modify aList in place, so the unmodified version is destroyed. Heres how you could create a new list and leave aList unchanged
>>> aList = [
... [1,2,3,4,3,2],
... [2,3,4,5,4,3],
... [2,1,2,3,4,3]
... ]
>>> new_aList = []
>>> for item in aList:
... new_aList.append(list(reversed(item)))
...
>>> new_aList
[[2, 3, 4, 3, 2, 1], [3, 4, 5, 4, 3, 2], [3, 4, 3, 2, 1, 2]]
another way to reverse a list is to use this extended slice trick. The -1 means step through the list in steps of -1 ie. backwards.
>>> new_aList = []
>>> for item in aList:
... new_aList.append(item[::-1])
...
>>> new_aList
[[2, 3, 4, 3, 2, 1], [3, 4, 5, 4, 3, 2], [3, 4, 3, 2, 1, 2]]
Instead of explicitly making an empty list and appending to it, it is more usual to write a loop like this as a list comprehension
>>> new_aList = [item[::-1] for item in aList]
>>> new_aList
[[2, 3, 4, 3, 2, 1], [3, 4, 5, 4, 3, 2], [3, 4, 3, 2, 1, 2]]
bList = []
for l in aList:
l.reverse()
bList.append(l)
For more fine-grained manipulation of lists, the position of values can be swapped using tuple unpacking (which neatly avoids having to use temporary variables):
aList[0][1], aList[0][3] = aList[0][3], aList[0][1]
After this operation, the second and fourth values would change places, and so aList[0] would look like this:
[1, 4, 3, 2, 3, 2]
Related
I want to create a date list that- contains the list of dates of one week but each date should be there 4 times in that list. like this:
[1-jan-2018, 1-jan-2018, 1-jan-2018, 1-jan-2018, 2-jan-2018, 2-jan-2018, 2-jan-2018, 2-jan-2018, 3-jan-2018, 3-jan-2018, 3-jan-2018, 3-jan-2018, 4-jan-2018, 4-jan-2018, 4-jan-2018, 4-jan-2018, 5-jan-2018, 5-jan-2018, 5-jan-2018, 5-jan-2018, 6-jan-2018, 6-jan-2018, 6-jan-2018, 6-jan-2018,7-jan-2018, 7-jan-2018, 7-jan-2018, 7-jan-2018]
I don't exactly have the idea how to do it but here is my attempt:
import pandas as pd
timeSeries = list(pd.date_range(start='1/1/2020', end='7/1/2020'))
print(timeSeries)
This will just create the list of dates of one week but I want the answer in the above format. Can someone please help?
How to duplicate items in a list
A solution is create various list with each element of your primary list repeated N time. In this example, I will duplicated each element four times, so:
old_list = [1,2,3,4]
# [i,i,i,i] will clone each item four times.
new_list = list([i,i,i,i] for i in old_list)
# new_list = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]
But, now you will have a list of lists, so you need to transform that result into a list of elements, this operation is called flat. In order to do this in python, you can use the itertools.chain.
import itertools
old_list = [1,2,3,4]
# [i,i,i,i] will clone each item four times.
new_list = list([i,i,i,i] for i in old_list)
# new_list = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]
new_list_flatten = list(itertools.chain(*new_list))
# new_list_flatten = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
You can avoid the usage of * operation by calling itertools.chain.from_iterable:
import itertools
old_list = [1,2,3,4]
# [i,i,i,i] will clone each item four times.
new_list = list([i,i,i,i] for i in old_list)
# new_list = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]
new_list_flatten = list(itertools.chain.from_iterable(new_list))
# new_list_flatten = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
Therefore, this is a code that do what you want:
import itertools
import pandas as pd
time_series = list(pd.date_range(start='1/1/2020', end='7/1/2020'))
newseries = list( itertools.chain.from_iterable((i,i,i,i) for i in time_series) )
print(newseries)
I have a list path. Initially, it looks like this:
path = [2, 1, 3, 0]
I will have to run many operations on path in different steps of my process. But I have to store the contents of path after each step. I mean,
path = [2, 1, 3, 0]
path.pop() # need to store
path.pop() # same
path.append(9) # same
path.append(5) # same
So, after each of these steps path will look like this:
path = [2, 1, 3, 0]
path = [2, 1, 3]
path = [2, 1]
path = [2, 1, 9]
path = [2, 1, 9, 5]
As I need each of these so I want to store them in a 2D list. Therefore, in the end, the 2D list will look like this:
But the problem is, initially I don't know how large custom_list can grow? It's decided only at runtime. So what I thought is that after each step I will append the path to my custom_list so when the process is finished custom_list will store all the path's content as mentioned above. Like this:
custom_list = [[2, 1, 3, 0], [2, 1, 3], [2, 1], [2, 1, 9], [2, 1, 9, 5]]
But for this .append does not work. How to solve this problem?
Also is this efficient to implement this with list or should I choose any other way i.e. numpy array or anything else? If so then kindly mention and explain
Edit
Code:
list = [2,1,3,0]
my_list = [[]]
my_list.append(list)
list.pop()
list.pop()
list.append(9)
my_list.append(list)
list.append(5)
my_list.append(list)
my_list
>>>[[], [2, 1, 9, 5], [2, 1, 9, 5], [2, 1, 9, 5]]
Would be better to use an immutable collection (create a tuple for each state you want to track):
list = [2,1,3,0]
my_list = [()]
my_list.append(tuple(list))
list.pop()
list.pop()
list.append(9)
my_list.append(tuple(list))
list.append(5)
my_list.append(tuple(list))
my_list
# produces [(), (2, 1, 3, 0), (2, 1, 9), (2, 1, 9, 5)]
Your problem is that list is being modified in place, and then my_list is just containing multiple references to the same list. tuple cannot be modified in place. Each addition is a completely new instance.
If for some reason you need to stick with lists, you can use list[:] to create a copy:
my_list.append(list[:])
Use copy.deepcopy.
Whenever you doing appending and poping all operation performing on list so after lastoperation whatever the list have values its printing the same
In [10]: path=[1,2,3,4]
In [11]: path2=path
In [12]: path.pop()
Out[12]: 4
In [13]: path2
Out[13]: [1, 2, 3]
In [14]: #using deepcopy
In [15]: import copy
In [16]: path=[1,2,3,4]
In [17]: path2=copy.deepcopy(path)
In [18]: path.pop()
Out[18]: 4
In [19]: path2
Out[19]: [1, 2, 3, 4]
Modified your code :
import copy
list = [2,1,3,0]
my_list = [] #take the inly list
my_list.append(copy.deepcopy(list))
list.pop()
list.pop()
list.append(9)
my_list.append(copy.deepcopy(list))
list.append(5)
my_list.append(copy.deepcopy(list))
print(my_list)
result:
[[2, 1, 3, 0], [2, 1, 9], [2, 1, 9, 5]]
use path[:] or path.copy() to make a copy
cusls = []
path = [2, 1, 3, 0]
cusls.append(path[:])
path.pop() # need to store
cusls.append(path[:])
path.pop() # same
cusls.append(path[:])
path.append(9) # same
cusls.append(path[:])
path.append(5) # same
cusls.append(path[:])
cusls
Out[25]: [[2, 1, 3, 0], [2, 1, 3], [2, 1], [2, 1, 9], [2, 1, 9, 5]]
I want to generate or return an append-accumulated list from a given list (or iterator). For a list like [1, 2, 3, 4], I would like to get, [1], [1, 2], [1, 2, 3] and [1, 2, 3, 4]. Like so:
>>> def my_accumulate(iterable):
... grow = []
... for each in iterable:
... grow.append(each)
... yield grow
...
>>> for x in my_accumulate(some_list):
... print x # or something more useful
...
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
This works but is there an operation I could use with itertools.accumulate to facilitate this? (I'm on Python2 but the pure-python implementation/equivalent has been provided in the docs.)
Another problem I have with my_accumulate is that it doesn't work well with list(), it outputs the entire some_list for each element in the list:
>>> my_accumulate(some_list)
<generator object my_accumulate at 0x0000000002EC3A68>
>>> list(my_accumulate(some_list))
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
Option 1:
I wrote my own appending accumulator function to use with itertools.accumulate but considering the LoC and final useful-ness, it seems like a waste of effort, with my_accumulate being more useful, (though may fail in case of empty iterables and consumes more memory since grow keeps growing):
>>> def app_acc(first, second):
... if isinstance(first, list):
... first.append(second)
... else:
... first = [first, second]
... return first
...
>>> for x in accumulate(some_list, app_acc):
... print x
...
1
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
>>> list(accumulate(some_list, app_acc)) # same problem again with list
[1, [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
(and the first returned elem is not a list, just a single item)
Option 2: Figured it would be easier to just do incremental slicing but using the ugly iterate over list length method:
>>> for i in xrange(len(some_list)): # the ugly iterate over list length method
... print some_list[:i+1]
...
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
The easiest way to use accumulate is to make each item in the iterable a list with a single item and then the default function works as expected:
from itertools import accumulate
acc = accumulate([el] for el in range(1, 5))
res = list(acc)
# [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
This question already has answers here:
Transpose nested list in python
(4 answers)
Closed 8 years ago.
I Have list of list, I want to loop through the list and for every iteration i want to access the ith subelements of the list.
eg:
a = [[1, 3, 4], [2, 4, 4], [3, 7, 5]]
i want to do something like this
for i in range(len(a)):
x=a[i]
for 1st iteration I want to access the 0th element from all the sub list (i.e) 1,2,3
for 2nd iteration I want to access the 1st element from all the sub list (i.e) 3,4,7
I tried several approaches but failed, is there any trick to do that
You can use zip
s = [[1, 3, 4], [2, 4, 4], [3, 7, 5]]
print zip(*s)
#[(1, 2, 3), (3, 4, 7), (4, 4, 5)]
def get_column(n, table):
result = []
for line in table:
result.append(line[n])
return result
test = [[1,2,3],[4,5,6],[7,8,9]]
for i in range(len(test[0])):
print(get_column(i, test))
Execution :
[1, 4, 7]
[2, 5, 8]
[3, 6, 9]
Alternative for the zip method,
>>> a = [[1, 3, 4], [2, 4, 4], [3, 7, 5]]
>>> new_list = []
>>> for k,v in enumerate(a):
... new_list.append([])
... for item in a:
... new_list[-1].append(item[k])
...
>>> new_list
[[1, 2, 3], [3, 4, 7], [4, 4, 5]]
As mentioned in above answer you can use an elegant way with zip but if you want to access to the columns in every iteration and dont want to get all of them in one time itertools.izip is what you are looking for , itertools.izip return a generator that you can get the result in every iteration :
>>> from itertools import izip
>>> for i in izip(*a):
... print i
...
(1, 2, 3)
(3, 4, 7)
(4, 4, 5)
Also you can use pop in a for loop (less performance than izip):
>>> a = [[1, 3, 4], [2, 4, 4], [3, 7, 5]]
>>> test=[]
>>> for i in range(len(a[0])):
... for j in a:
... test.append(j.pop(0))
... print test
... test=[]
...
[1, 2, 3]
[3, 4, 7]
[4, 4, 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)