I have a list that contain lists:
mylist=[[2],[9],[3],[5],[7]]
Is there a way in python to get the value of the inner list (not just print it)?
Therefore, we would get integer 2 from the list mylist[0]. Without iterating the whole mylist.
If you want to get a specific value, use mylist[instance][0].
This would work, because it gets the ith value, but then gets the 0th value of that because it is still a list:
>>> mylist=[[2],[9],[3],[5],[7]]
>>> mylist[0]
[2]
>>> mylist[0][0]
2
>>>
Alternatively, you could flatten it and then access it normally:
>>> mylist=[[2],[9],[3],[5],[7]]
>>> mylist = [item for sub in mylist for item in sub]
>>> mylist
[2, 9, 3, 5, 7]
>>> mylist[0]
2
>>>
A list of lists is similar to having a 2-D array. To reference an element of the inner list, just use
mylist[i][j]
where i refers to the index of the list and j to the element in that list.
In the case of 2, this would be:
mylist[0][0]
Think of your list like this:
mylist=
[[2],
[9],
[3],
[5],
[7]]
mylist[0] = [2] which is an array, to access the number in the array mylist as explained is mylist[0][0] which = the int 2
eg
mylist[1][0] = 2
If mylist was
mylist=
[[2, 3],
[9, 10],
[3, 4],
[5, 6],
[7, 8]]
mylist[0][1] = 3 and mylist[1][1] = 10
mylist=[[2],[9],[3],[5],[7]]
newList=[]
for each in str(mylist).replace('[','').replace(']','').strip().split(','):
newList.append(int(each))
print newList
or
newList = eval('[' + str(mylist).replace('[','').replace(']','').strip() +']')
Related
I want to remove duplicate items from lists in sublists on Python.
Exemple :
myList = [[1,2,3], [4,5,6,3], [7,8,9], [0,2,4]]
to
myList = [[1,2,3], [4,5,6], [7,8,9], [0]]
I tried with this code :
myList = [[1,2,3],[4,5,6,3],[7,8,9], [0,2,4]]
nbr = []
for x in myList:
for i in x:
if i not in nbr:
nbr.append(i)
else:
x.remove(i)
But some duplicate items are not deleted.
Like this : [[1, 2, 3], [4, 5, 6], [7, 8, 9], [0, 4]]
I still have the number 4 that repeats.
You iterate over a list that you are also modifying:
...
for i in x:
...
x.remove(i)
That means that it may skip an element on next iteration.
The solution is to create a shallow copy of the list and iterate over that while modifying the original list:
...
for i in x.copy():
...
x.remove(i)
You can make this much faster by:
Using a set for repeated membership testing instead of a list, and
Rebuilding each sublist rather than repeatedly calling list.remove() (a linear-time operation, each time) in a loop.
seen = set()
for i, sublist in enumerate(myList):
new_list = []
for x in sublist:
if x not in seen:
seen.add(x)
new_list.append(x)
myList[i] = new_list
>>> print(myList)
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [0]]
If you want mild speed gains and moderate readability loss, you can also write this as:
seen = set()
for i, sublist in enumerate(myList):
myList[i] = [x for x in sublist if not (x in seen or seen.add(x))]
Why you got wrong answer: In your code, after scanning the first 3 sublists, nbr = [1, 2, 3, 4, 5, 6, 7, 8, 9]. Now x = [0, 2, 4]. Duplicate is detected when i = x[1], so x = [0, 4]. Now i move to x[2] which stops the for loop.
Optimization has been proposed in other answers. Generally, 'list' is only good for retrieving element and appending/removing at the rear.
A = [[1, 2, 4],
[3, 5, 6],
[7,8,9]]
def sumof(A,3):
We need to find the lowest sum of 3 elements
here 1 + 2 + 3 = 6 so output is (1,2,3)
Can we do by using zip
one basic solution, convert nested list into flat list, sort it,slice sorted list and sum:
A = [[1, 2, 4],
[3, 5, 6],
[7,8,9]]
def sumof(A, n):
# convert nested list into flat list
flat_list = [item for sublist in A for item in sublist]
return sum(sorted(flat_list)[:n])
print (sumof(A,3))
If you have a large array, you can do this without sorting the list,
which is a little faster like
from operator import add
from functools import reduce
A = [[1, 2, 4],
[3, 5, 6],
[7,8,9]]
addlists = lambda l: reduce(add, l)
list_A = addlists(A)
result = [list_A.pop(list_A.index(min(list_A))) for _ in range(3)]
It's a little more complicated, though the modules imported are really useful.
So I am trying to delete elements from an array and do some calculations with this array. The thing is, I want to still keep a copy of the original array, so I made a new array and assigned it the values of the original array. The thing is, whenever I print out the length of the original and the new array, it gives me the same length, but it gives me the length of the new array. How do I make a new array with the same values as 'a', but without changing 'a'
a = [2, 4, 5, 7, 8, 9]
b = []
b = a
for _ in range(2):
m = min(b)
b[:] = (x for x in b if x != m)
print(len(b))
print(len(a))
Saying b = a just creates a new variable that references the existing list object. To make a copy of a list you could use the list() function or list slicing:
b = list(a)
b = a[:]
That said, to create a new list from an existing one filtering out some elements you could use a list comprehension:
from heapq import nsmallest
m = nsmallest(2, a)
b = [x for x in a if x not in m]
You are not copying - you are aliasing . You give a second name to the same array (which is a list btw). try b = a[:] this will copy it - only works if the lists content is immutable.
If your list contains other lists it will "copy" the reference to that list but not the nested lists contents - that would be a deepcopy().
If you want to remove the lowest 2 you could also resort to sorting and slicing (you list is already sorted so no sort needed)
a = [2, 4, 5, 7, 8, 9]
b = a[2:] // slice, ignore first 2 entries which are the lowest 2
c = sorted(a)[2:] // implicitly creates a new sorted list, ignore lowest 2
print(b)
print(c)
Output:
[5, 7, 8, 9]
[5, 7, 8, 9]
There is difference between list and list[:].
When reading, list is a reference to the original list, and list[:] shallow-copies the list.
When assigning, list (re)binds the name and list[:] slice-assigns, replacing what was previously in the list.
However, if the list elements are lists themselves, even list1 = list[:] has its problems. Consider:
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b = a[:]
>>> b[0].remove(2)
>>> b
[[1, 3], [4, 5, 6], [7, 8, 9]]
>>> a
[[1, 3], [4, 5, 6], [7, 8, 9]]
This happens because each list element being copied to b is a list itself, and this copying of lists involves the same problem that occurs with the normal list1 = list2. The shortest way out is to explicitly copy every list element this way:
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b=[[j for j in i] for i in a]
>>> b
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> b[0].remove(2)
>>> b
[[1, 3], [4, 5, 6], [7, 8, 9]]
>>> a
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> a = [1, 2, [3, 4], 5]
>>> print(len(a))
4
The length of the list is 4, why is the element count 4 and not 5?
The element count in the outer list is 4. a[2] is one object. It doesn't matter here that that one object is also a list.
If you need to count the number of elements recursively, then do so yourself:
def recursive_element_count(ob):
if isinstance(ob, list):
return sum(recursive_element_count(elem) for elem in ob)
# anything that isn't a list counts as one element
return 1
Demo:
>>> def recursive_element_count(ob):
... if isinstance(ob, list):
... return sum(recursive_element_count(elem) for elem in ob)
... return 1
...
>>> a = [1, 2, [3, 4], 5]
>>> recursive_element_count(a)
5
Do you know sets from mathematic? That's similar in Python, in lists-tuples-sets etc. if there is a list in list or tuple in tuple etc. they are one element.
a=[1,2,3]
b=[2,3]
a.append(b)
print (a)
print (len(a))
Output:
>>>
[1, 2, 3, [2, 3]]
4
>>>
Thats because len(a)=4. [2,3] is an element of list(a).
As the inner list assumed as one object the len returned 4 . you can use the following code for calculate the length of all elements :
>>> a = [1, 2, [3, 4], 5]
>>> sum(len(i) if isinstance(i,list) else 1 for i in a)
5
isinstance() function used for check the type of object .
Say I have a list of lists
>>> s = [ [1,2], [3,4], [5,6] ]
I can access the items of the second list:
>>> s[1][0]
3
>>> s[1][1]
4
And the whole second list as:
>>> s[1][:]
[3, 4]
But why does the following give me the second list as well?
>>> s[:][1]
[3, 4]
I thought it would give me the second item from each of the three lists.
One can use list comprehension to achieve this (as in question 13380993), but I'm curious how to properly understand s[:][1].
s[:] returns a copy of a list. The next [...] applies to whatever the previous expression returned, and [1] is still the second element of that list.
If you wanted to have every second item, use a list comprehension:
[n[1] for n in s]
Demo:
>>> s = [ [1,2], [3,4], [5,6] ]
>>> [n[1] for n in s]
[2, 4, 6]
The behavior can be understood easily, if we decompose the command:
s[:]
will return the entire list:
[[1, 2], [3, 4], [5, 6]]
selecting [1] now gives the second list (python indexing starts at zero).
s[:][1] means take a shallow copy of s and give me the first element from that... While s[1][:] means give me a shallow copy of s[1]...
You may be confusing somethings that you've seen that utilise numpy which allows extended slicing, eg:
>>> a = np.array([ [1,2], [3,4], [5,6] ])
>>> a[:,1]
array([2, 4, 6])
Which with normal lists, as you say, can be done with a list-comp:
second_elements = [el[1] for el in s]
s[:] makes a copy of s, so the following [1] accesses the second element of that copy. Which is the same as s[1].
>>> s = [ [1,2], [3,4], [5,6] ]
>>> s[1]
[3, 4]
>>> s[:][1]
[3, 4]
s[1][:] means a shallow copy of the second item in s, which is [3,4].
s[:][1] means the second item in a shallow copy of s, which is also [3,4].
Below is a demonstration:
>>> s = [ [1,2], [3,4], [5,6] ]
>>> # Shallow copy of `s`
>>> s[:]
[[1, 2], [3, 4], [5, 6]]
>>> # Second item in that copy
>>> s[:][1]
[3, 4]
>>> # Second item in `s`
>>> s[1]
[3, 4]
>>> # Shallow copy of that item
>>> s[1][:]
[3, 4]
>>>
Also, [1] returns the second item, not the first, because Python indexes start at 0.