Nested lists python - python

Can anyone tell me how can I call for indexes in a nested list?
Generally I just write:
for i in range (list)
but what if I have a list with nested lists as below:
Nlist = [[2,2,2],[3,3,3],[4,4,4]...]
and I want to go through the indexes of each one separately?

If you really need the indices you can just do what you said again for the inner list:
l = [[2,2,2],[3,3,3],[4,4,4]]
for index1 in xrange(len(l)):
for index2 in xrange(len(l[index1])):
print index1, index2, l[index1][index2]
But it is more pythonic to iterate through the list itself:
for inner_l in l:
for item in inner_l:
print item
If you really need the indices you can also use enumerate:
for index1, inner_l in enumerate(l):
for index2, item in enumerate(inner_l):
print index1, index2, item, l[index1][index2]

Try this setup:
a = [["a","b","c",],["d","e"],["f","g","h"]]
To print the 2nd element in the 1st list ("b"), use print a[0][1] - For the 2nd element in 3rd list ("g"): print a[2][1]
The first brackets reference which nested list you're accessing, the second pair references the item in that list.

You can do this. Adapt it to your situation:
for l in Nlist:
for item in l:
print item

The question title is too wide and the author's need is more specific. In my case, I needed to extract all elements from nested list like in the example below:
Example:
input -> [1,2,[3,4]]
output -> [1,2,3,4]
The code below gives me the result, but I would like to know if anyone can create a simpler answer:
def get_elements_from_nested_list(l, new_l):
if l is not None:
e = l[0]
if isinstance(e, list):
get_elements_from_nested_list(e, new_l)
else:
new_l.append(e)
if len(l) > 1:
return get_elements_from_nested_list(l[1:], new_l)
else:
return new_l
Call of the method
l = [1,2,[3,4]]
new_l = []
get_elements_from_nested_list(l, new_l)

n = [[1, 2, 3], [4, 5, 6, 7, 8, 9]]
def flatten(lists):
results = []
for numbers in lists:
for numbers2 in numbers:
results.append(numbers2)
return results
print flatten(n)
Output: n = [1,2,3,4,5,6,7,8,9]

I think you want to access list values and their indices simultaneously and separately:
l = [[2,2,2],[3,3,3],[4,4,4],[5,5,5]]
l_len = len(l)
l_item_len = len(l[0])
for i in range(l_len):
for j in range(l_item_len):
print(f'List[{i}][{j}] : {l[i][j]}' )

Related

Unpack List with key value pair

I need to get the value(the right hand value after the colon) in this list
list = [apple:tuesday, banana:wednesday, guava:thursday]
first your list will be like
list1=["apple:tuesday", "banana:wednesday", "guava:thursday"]
k=0
for i in list1:
x=i.split(":")
print(x)
list1[k]=x[1]
k+=1
print(list1)
i hope this is what you were trying to do
you can do this by list comprehension.it's easy and fast
l = ["apple:tuesday", "banana:wednesday", "guava:thursday"]
new_l = [item.split(":")[1] for item in l]
list comprehension work like this
l = [i for i in range(5)]
# l = [0,1,2,3,4]

How to extract the first element (as a list of string) of the n-th elements of a nested list, Python

I am a fresh python beginner and trying to extract the first element of the first n-th elements of a nested list. But it doesn't work so far.
Say:
list = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
Goal:
list_new = ['Anna','Peter','Zani'...(#until the n-th elements)]
If I want to first element of all the elements in the list, it should be:
for i in list:
for j in i:
print j[0]
But what if i only want to strip the first element of the n-th elements of the list, instead of all the elements.
For example for the first 2 elements:
I tried:
for i in list[0:2]:
for j in i:
print j[0]
but it didn't work.
What's more, if i want to give the value of n later by using
def sheet(list, n)
and the return statement, how could i do it?
Thank you very much!!
lst = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
n = 2
print(lst[n][0])
Output:
Zani
---Updated answer for the details added in the question---
l = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
n = 2
for i in range(n):
print(l[i][0])
Output:
Anna
Peter
You can use a list comprehension. Given an input list of lists L:
L_new = [i[0] for i in L[:n]]
Functionally, you can use operator.itemgetter. In addition, you can use itertools.islice to avoid creating an intermediary list:
from operator import itemgetter
from itertools import islice
L_new = list(map(itemgetter(0), islice(L, 0, n)))
Be careful, list is reserved for the built-in function list() in python, you should not use 'list' as variable name.
To get the first element of each nested list :
l = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
for e in l:
print(e[0])
Prints :
Anna
Peter
Zani
Lily
To do the same on the nth first elements :
def sheet(l, n):
return [e[0] for e in l[:n]]
sheet(l, 3)
Returns
['Anna', 'Peter', 'Zani']
EDIT
def sheet(l, n):
for e in l[:n]
return [e[0]]
This code only returns ['Anna'] because the return statement stops the function. The for loop is stopped at the first element.
def sheet(l, n):
return [e[0] for e in l[:n]]
is equivalent to :
def sheet(l, n):
result = [e[0] for e in l[:n]]
return result
which is equivalent to :
def sheet(l, n):
result = []
for e in l[:n]:
result.append(e[0])
return result
The for loop can ends before the return statement.
More informations here.
Just try this one which will be easier for you to understand:
n = int(input())
lst = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
lst_new = []
for item in lst[:n]:
name, *rest = item
lst_new.append(name)

Removing some of the duplicates from a list in Python

I would like to remove a certain number of duplicates of a list without removing all of them. For example, I have a list [1,2,3,4,4,4,4,4] and I want to remove 3 of the 4's, so that I am left with [1,2,3,4,4]. A naive way to do it would probably be
def remove_n_duplicates(remove_from, what, how_many):
for j in range(how_many):
remove_from.remove(what)
Is there a way to do remove the three 4's in one pass through the list, but keep the other two.
If you just want to remove the first n occurrences of something from a list, this is pretty easy to do with a generator:
def remove_n_dupes(remove_from, what, how_many):
count = 0
for item in remove_from:
if item == what and count < how_many:
count += 1
else:
yield item
Usage looks like:
lst = [1,2,3,4,4,4,4,4]
print list(remove_n_dupes(lst, 4, 3)) # [1, 2, 3, 4, 4]
Keeping a specified number of duplicates of any item is similarly easy if we use a little extra auxiliary storage:
from collections import Counter
def keep_n_dupes(remove_from, how_many):
counts = Counter()
for item in remove_from:
counts[item] += 1
if counts[item] <= how_many:
yield item
Usage is similar:
lst = [1,1,1,1,2,3,4,4,4,4,4]
print list(keep_n_dupes(lst, 2)) # [1, 1, 2, 3, 4, 4]
Here the input is the list and the max number of items that you want to keep. The caveat is that the items need to be hashable...
You can use Python's set functionality with the & operator to create a list of lists and then flatten the list. The result list will be [1, 2, 3, 4, 4].
x = [1,2,3,4,4,4,4,4]
x2 = [val for sublist in [[item]*max(1, x.count(item)-3) for item in set(x) & set(x)] for val in sublist]
As a function you would have the following.
def remove_n_duplicates(remove_from, what, how_many):
return [val for sublist in [[item]*max(1, remove_from.count(item)-how_many) if item == what else [item]*remove_from.count(item) for item in set(remove_from) & set(remove_from)] for val in sublist]
If the list is sorted, there's the fast solution:
def remove_n_duplicates(remove_from, what, how_many):
index = 0
for i in range(len(remove_from)):
if remove_from[i] == what:
index = i
break
if index + how_many >= len(remove_from):
#There aren't enough things to remove.
return
for i in range(index, how_many):
if remove_from[i] != what:
#Again, there aren't enough things to remove
return
endIndex = index + how_many
return remove_from[:index+1] + remove_from[endIndex:]
Note that this returns the new array, so you want to do arr = removeCount(arr, 4, 3)
Here is another trick which might be useful sometimes. Not to be taken as the recommended recipe.
def remove_n_duplicates(remove_from, what, how_many):
exec('remove_from.remove(what);'*how_many)
I can solve it in different way using collections.
from collections import Counter
li = [1,2,3,4,4,4,4]
cntLi = Counter(li)
print cntLi.keys()

Removing specific columns and rows from nested list

If for example I have glider = [[0,0,0,0],[1,2,3,4],[0,1,3,4],[0,0,0,0]], how would I go about deleting the first and last list as well as the first and last character per list if the nested lists varies. It would look like this after.
glider = [[2,3],[1,3]]
For example, I can't just simply use the del function because the dimensions will vary. ex:[[0,0,0,0,0],[1,2,3,4,5],[0,1,2,3,4],[0,0,0,0,0]]
, [[0,0,0],[1,2,3],[0,0,0]]
This is a small part of a bigger program but it has me stumped. Maybe the better method would be to to create a whole new list? Thank you.
You can do this using slicing and a temporary list:
glider = [[0,0,0,0],[1,2,3,4],[0,1,3,4],[0,0,0,0]]
glider = glider[1:-1]
templist = []
for i in glider:
templist.append(i[1:-1])
glider = templist
del templist
Output:
>>> glider
[[2, 3], [1, 3]]
You can create a new list with your given conditions
glider = [[y for y in x[1:-1]] for x in glider[1:-1]]
Try this:
glider = [[0,0,0,0],[1,2,3,4],[0,1,3,4],[0,0,0,0]]
def my_strip(lst):
if isinstance(lst, list):
lst = lst[1:-1]
for idx, val in enumerate(lst):
lst[idx] = my_strip(val)
return lst
print my_strip(glider)
Do you want something like:
a = [[0,0,0,0,0],[1,2,3,4,5],[0,1,2,3,4],[0,0,0,0,0]]
b = [k[1:-1] for k in a[1:-1]]
# remove consecutive equal items
if b:
res = [b[0]] + [k for i, k in enumerate(b[1:], 1) if k != b[i-1]]
else:
res = []

Python unflatten list based on second list

I have 2 Python lists:
list_a = [[['Ab'], ['Qr', 'Zr']], [['Gt', 'Mh', 'Nt'], ['Dv', 'Cb']]]
list_b = [['Ab', 'QrB', 'Zr'], ['GtB', 'MhB', 'Nt6B', 'DvB', 'Cb6B5']]
I need to un-flatten list_b based on list_a. I need:
list_c = [['Ab'], ['QrB', 'Zr'], [['GtB', 'MhB', 'Nt6B'], ['DbB', 'Cb6B5']]]
Is there a way to get this list_c?
Additional Information:
The lists will always be defined such that:
A partial string from list_a will always be found in list_b. eg. for Gt in one list, there will be either Gt or GtB in the 2nd list.
Entries in each list cannot be in a different order - i.e. if Qr comes before Zr in one list then it (Qr or QrB) must come before Zr in the 2nd list.
Each list can have a maximum of 20 strings in it.
Each list has only unique strings.. eg. Gt cannot occur 2 or more times in any list.
Attempt:
Here is what I have tried:
list_c = [[],[]]
for ty,iten in enumerate(list_b):
for q in iten:
for l_e in list_a:
for items in l_e:
for t,qr in enumerate(items):
if qr in q:
list_c[ty].append([q])
the output of this is:
[[['Ab'], ['QrB'], ['Zr']], [['GtB'], ['MhB'], ['Nt6B'], ['DbB'], ['Cb6B5']]]
The problem is that ['QrB'], ['Zr'] should be combined ['QrB','Zr'] just like they are combined in list_a.
Attempt 2:
for ty,iten in enumerate(list_b):
for q in iten:
for l_e,m in enumerate(list_a):
for ss,items in enumerate(m):
for t,qr in enumerate(items):
if qr in q:
list_a[l_e][ss][t] = q
This works and produces the required output:
[[['Ab'], ['QrB', 'Zr']], [['GtB', 'MhB', 'Nt6B'], ['DvB', 'Cb6B5']]]
However, it (attempt 2) is too long and I would like to know: it does not seem that this is the proper way to do this in Python. Is there is a more Pythonic way to do this?
If all you care about is the length of the sublists in list_a then can transform list_a into its sublist lengths and then use that to slice the sublists of list_b:
# Transform list_a into len of sublists, (generator of generators :)
index_a = ((len(l2) for l2 in l1) for l1 in list_a))
list_c = []
for flatb, index in zip(list_b, index_a):
splitb = []
s = 0
for i in index:
splitb.append(flatb[s:s+i])
s += i
list_c.append(splitb)
Value of list_c:
[[['Ab'], ['QrB', 'Zr']], [['GtB', 'MhB', 'Nt6B'], ['DvB', 'Cb6B5']]]
This is a recursive variant for arbitrary depth of nesting. Not too pretty, but should work.
list_a = [[['Ab'], ['Qr', 'Zr']], [['Gt', 'Mh', 'Nt'], ['Dv', 'Cb']]]
list_b = [['Ab', 'QrB', 'Zr'], ['GtB', 'MhB', 'Nt6B', 'DvB', 'Cb6B5']]
def flatten(l):
for el in l:
if isinstance(el, list):
for sub in flatten(el):
yield sub
else:
yield el
def flitten(l1, l2, i):
result = []
for j in l1:
if isinstance(j, list):
i, res = flitten(j, l2, i)
result.append(res)
else:
result.append(l2[i])
i += 1
return i, result
def flutten(l1, l2):
i, result = flitten(l1, list(flatten(l2)), 0)
return result
print(flutten(list_a, list_b))
# prints [[['Ab'], ['QrB', 'Zr']], [['GtB', 'MhB', 'Nt6B'], ['DvB', 'Cb6B5']]]
Your code does not look too long given the fairly complicated nature of the task (find a list within a list within a list and match it to a list within another list according to the first two letters, and replace the original value with the matched value retaining the nested structure of the original list...)
You could at least eliminate one of the loops like this:
for sub_a, sub_b in zip(list_a, list_b):
for inner_a in sub_a:
for i, a in enumerate(inner_a):
for b in sub_b:
if b.startswith(a):
inner_a[i] = b
If you want a more general solution it will probably involve recursion as in #Tibor's answer.
EDIT: Given the extra information you have supplied, you could recursively work through list_a, replacing all the short strings with their full versions from an iterator based on the flattened version of list_b. This uses the fact that the strings appear in the same order in both lists with no duplicates.
def replace_abbreviations(L, full_names):
for i, item in enumerate(L):
if isinstance(item, basestring):
L[i] = full_names.next()
elif isinstance(item, list):
replace_abbreviations(item, full_names)
replace_abbreviations(list_a, (item for L in list_b for item in L))
Alternatively you can get a flattened list of the indices of each string in both lists and then loop through those:
def flat_indices(L):
for i, item in enumerate(L):
if isinstance(item, list):
for j, inner_list in flat_indices(item):
yield (j, inner_list)
else:
yield (i, L)
for (a, i), (b, j) in zip(flat_indices(list_a), flat_indices(list_b)):
a[i] = b[j]

Categories

Resources