Indexing a nested list in python - python

Given data as
data = [ [0, 1], [2,3] ]
I want to index all first elements in the lists inside the list of lists. i.e. I need to index 0 and 2.
I have tried
print data[:][0]
but it output the complete first list .i.e.
[0,1]
Even
print data[0][:]
produces the same result.
My question is specifically how to accomplish what I have mentioned. And more generally, how is python handling double/nested lists?

Using list comprehension:
>>> data = [[0, 1], [2,3]]
>>> [lst[0] for lst in data]
[0, 2]
>>> [first for first, second in data]
[0, 2]
Using map:
>>> map(lambda lst: lst[0], data)
[0, 2]
Using map with operator.itemgetter:
>>> import operator
>>> map(operator.itemgetter(0), data)
[0, 2]
Using zip:
>>> zip(*data)[0]
(0, 2)

With this sort of thing, I generally recommend numpy:
>>> data = np.array([ [0, 1], [2,3] ])
>>> data[:,0]
array([0, 2])
As far as how python is handling it in your case:
data[:][0]
Makes a copy of the entire list and then takes the first element (which is the first sublist).
data[0][:]
takes the first sublist and then copies it.

The list indexing or nesting in general (be it dict, list or any other iterable) works Left to Right. Thus,
data[:][0]
would work out as
(data[:]) [0] == ([[0, 1], [2,3]]) [0]
which ultimately gives you
[0, 1]
As for possible workaronds or proper methods, falsetru & mgilson have done a good job in that regards.

try this:
print [x for x, y in data[:]]

Related

Set rows in Python 2D array to another row without Numpy?

I want to "set" the values of a row of a Python nested list to another row without using NumPy.
I have a sample list:
lst = [[0, 0, 1],
[0, 2, 3],
[5, 2, 3]]
I want to make row 1 to row 2, row 2 to row 3, and row 3 to row 1. My desired output is:
lst = [[0, 2, 3],
[5, 2, 3],
[0, 0, 1]]
How can I do this without using Numpy?
I tried to do something like arr[[0, 1]] = arr[[1, 0]] but it gives the error 'NoneType' object is not subscriptable.
One very straightforward way:
arr = [arr[-1], *arr[:-1]]
Or another way to achieve the same:
arr = [arr[-1]] + arr[:-1]
arr[-1] is the last element of the array. And arr[:-1] is everything up to the last element of the array.
The first solution builds a new list and adds the last element first and then all the other elements. The second one constructs a list with only the last element and then extends it with the list containing the rest.
Note: naming your list an array doesn't make it one. Although you can access a list of lists like arr[i1][i2], it's still just a list of lists. Look at the array documentation for Python's actual array.
The solution user #MadPhysicist provided comes down to the second solution provided here, since [arr[-1]] == arr[-1:]
Since python does not actually support multidimensional lists, your task becomes simpler by virtue of the fact that you are dealing with a list containing lists of rows.
To roll the list, just reassemble the outer container:
result = lst[-1:] + lst[:-1]
Numpy has a special interpretation for lists of integers, like [0, 1], tuples, like :, -1, single integers, and slices. Python lists only understand single integers and slices as indices, and do not accept tuples as multidimensional indices, because, again, lists are fundamentally one-dimensional.
use this generalisation
arr = [arr[-1]] + arr[:-1]
which according to your example means
arr[0],arr[1],arr[2] = arr[1],arr[2],arr[0]
or
arr = [arr[2]]+arr[:2]
or
arr = [arr[2]]+arr[:-1]
You can use this
>>> lst = [[0, 0, 1],
[0, 2, 3],
[5, 2, 3]]
>>> lst = [*lst[1:], *lst[:1]]
>>>lst
[[0, 2, 3],
[5, 2, 3],
[0, 0, 1]]

Get the duplicate elements from a list of lists [duplicate]

This question already has answers here:
How do I find the duplicates in a list and create another list with them?
(42 answers)
Closed 8 months ago.
Suppose that I have a list of lists, e.g.
example_list = [[0, 0], [0, 1], [0, 1], [5, 4]]
I want a reasonably fast method of obtaining a list formed exclusively of elements that appear at least twice in the original list. In this example, the new list would be
new_list = [[0, 1]]
since [0, 1] is the only duplicate entry. I have spent lots of time on Stackoverflow looking for a solution, but none of them seem to work for me (details below). How should I proceed in this instance?
Unsuccessful attempts. One solution which does work is to write something like
new_list = [x for x in example_list if example_list.count(x) > 1]
However, this is too slow for my purposes.
Another solution (suggested here) is to write
totals = {}
for k,v in example_list:
totals[k] = totals.get(k,0) + v
totals.items()
[list(t) for t in totals.items()]
print(totals)
I may have misunderstood what the author is suggesting, but this doesn't work for me at all: it prints {0: 2, 5: 4} in the terminal.
A final solution (also suggested on this page) is import Counter from collections and write
new_list = Counter(x for x, new_list in example_list for _ in xrange(new_list))
map(list, new_list.iteritems())
This flags an error on xrange and iteritems (I think it's a Python3 thing?), so I tried
new_list = Counter(x for x, new_list in example_list for _ in range(new_list))
map(list, new_list.items())
which yielded Counter({5: 4, 0: 2}) (again!!), which is of course not what I am after...
You can use Counter to create a dictionary of counts of elements in example_list. But each element should be converted to a tuple to make it hashable. Then, you can filter the elements that meet your criteria.
from collections import Counter
d = Counter([tuple(x) for x in example_list])
[list(k) for k, v in d.items() if v >= 2]
# [[0, 1]]
You could count the values of the inner lists. First, is to iterate the list - but really you want to iterate the values of the outer list. itertools.chain.from_iterable does that for you. Feed it in collections.Counter and you get a count of all of the values. A list comprehension can select the values you want and then place that in an outer list.
>>> example_list = [[0, 0], [0, 1], [0, 1], [5, 4]]
>>> import collections
>>> import itertools
>>> counts = collections.Counter(itertools.chain.from_iterable(example_list))
>>> counts
Counter({0: 4, 1: 2, 5: 1, 4: 1})
>>> selected = [k for k,v in counts.items() if v >= 2]
>>> result = [selected]
>>> result
[[0, 1]]

solving problems for lists in python

How to write a code which takes two lists as input and returns multiplication for the lists
e.g Result should look like this.
First-list [1,2]
Second-list [2,1]
Your result [2,1,4,2]
I have tried with the code
list1=[1,2]
list2=[2,1]
list3=list1*list2
First-list =[1,2]
Second-list=[2,1]
Couldn't find a duplicate (I'll delete if anyone does)
You can use a list comprehension
>>> a = [1, 2]
>>> b = [2, 1]
>>> [x * y for x in a for y in b]
[2, 1, 4, 2]

List of strings to array of integers

From a list of strings, like this one:
example_list = ['010','101']
I need to get an array of integers, where each row is each one of the strings, being each character in one column, like this one:
example_array = np.array([[0,1,0],[1,0,1]])
I have tried with this code, but it isn't working:
example_array = np.empty([2,3],dtype=int)
i = 0 ; j = 0
for string in example_list:
for bit in string:
example_array[i,j] = int(bit)
j+=1
i+=1
Can anyone help me? I am using Python 3.6.
Thank you in advance for your help!
If all strings are the same length (this is crucial to building a contiguous array), then use view to efficiently separate the characters.
r = np.array(example_list)
r = r.view('<U1').reshape(*r.shape, -1).astype(int)
print(r)
array([[0, 1, 0],
[1, 0, 1]])
You could also go the list comprehension route.
r = np.array([[*map(int, list(l))] for l in example_list])
print(r)
array([[0, 1, 0],
[1, 0, 1]])
The simplest way is to use a list comprehension because it automatically generates the output list for you, which can be easily converted to a numpy array. You could do this using multiple for loops, but then you are stuck creating your list, sub lists, and appending to them. While not difficult, the code looks more elegant with list comprehensions.
Try this:
newList = np.array([[int(b) for b in a] for a in example_list])
newList now looks like this:
>>> newList
... [[0, 1, 0], [1, 0, 1]]
Note: there is not need to invoke map at this point, though that certainly works.
So what is going on here? We are iterating through your original list of strings (example_list) item-by-item, then iterating through each character within the current item. Functionally, this is equivalent to...
newList = []
for a in example_list:
tmpList = []
for b in a:
tmpList.append(int(b))
newList.append(tmpList)
newList = np.array(newList)
Personally, I find the multiple for loops to be easier to understand for beginners. However, once you grasp the list comprehensions you probably won't want to go back.
You could do this with map:
example_array = map(lambda x: map(lambda y: int(y), list(x)), example_list)
The outer lambda performs a list(x) operation on each item in example_list. For example, '010' => ['0','1','0']. The inner lambda converts the individual characters (resultants from list(x)) to integers. For example, ['0','1','0'] => [0,1,0].

python: find the indeces of nested list by condition

To get the list indeces that satifies a condition, say None I can do:
[x for (x, e) in enumerate(my_list) if e is None]
But I can not get my head around what to do with a nested list using the same scheme as above. For instance how to find the indeces of my_nlist where the first element in the nested (inner) lists are None.
my_nlist = [[None, 2], [13, 2], [None, 1]]
The expected result would be:
[0,2]
Same as the previous one just use a tuple as the items throwaway variable:
In [5]: [ind for ind, (i, j) in enumerate(my_nlist) if i is None]
Out[5]: [0, 2]
An approach with numpy (maybe clearer than base python but needs a library):
import numpy as np
np.where([None in i for i in L])
#(array([0, 2], dtype=int64),)

Categories