What would be the shortest way to count the number of odd numbers in a list of lists like this with arbitrary dimensions, not necessarily 5x5:
list_of_lists = [[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
I tried, but i'd guess there's shorter:
counter = 0
for row in list_of_lists:
for i in row:
if i % 2 != 0:
counter += 1
print(counter)
If you always have one level of flat lists inside the main list you can use an inner loop to flatten, summing the result of each i % 2 which will be 1 for odd and 0 for even numbers:
list_of_lists = [[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
print(sum(i % 2 for sub in list_of_lists for i in sub))
Or use itertools.chain to do the flattening:
from itertools import chain
print(sum(i % 2 for i in chain(*list_of_lists)))
If you had arbitrary nesting, recursion would be an easy way to approach the problem:
def flat(lst):
for i in lst:
if isinstance(i, list):
for j in flat(i):
yield j % 2
else:
yield i % 2
print(sum(flat(list_of_lists)))
The numpy way of counting for a contrast:
import numpy as np
list_of_lists = [[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
l = np.array(list_of_lists)
print len(l[l%2!=0])
l[l%2!=0] returns all the elements that satisfy the condition l%2!=0 and len() counts it.
PS : This of course assumes that the list_of_lists is rectangular. For a solution that allows different length for each inner-list, see Padraic's answer.
Related
I am working on a project and I need to be able to create a function that takes in a value (n) and returns a matrix with increasing values.
ex: Given x = 2, return = [[1],[1, 2]]
Given x = 5, return = [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4],[1, 2, 3, 4, 5]]
Below is what I have thus far:
def matrixIncrease(n):
lst = []
for i in range(n):
lst.append([])
for j in range(0, n):
lst[i].append(j)
return lst
print(matrixIncrease(3))
This will just return
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
So it looks like the correct amount of inner list are being created. But, the values inside the list are not increasing correctly. Any suggestions?
Maybe you could try this List Comprehension way:
It's quite self-explnatory in the code, just play/experiment with different i and j to see the effects of changes...
Basically the j is to iterate and increase the numbers in each loop.
def create_sub(n):
''' create n sub_lists: each list has increasing items:
[1], [1, 2], [1, 2, 3], .... [1, ... n] '''
sub_matrix = [[j +1 for j in range(0, i)] # j - for col values
for i in range(1, n + 1)] # i - control rows
return sub_matrix
>>>create_sub(5)
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
>>>create_sub(8)
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7, 8]]
You could try this:
all_ = []
def matrixIncrease(n):
if n == 1:
all_.append([1])
return[1]
j=[]
for i in range(1,n+1):
j.append(i)
matrixIncrease(n-1)
all_.append(j)
matrixIncrease(7)
print(all_)
I would like to achieve something like this:
length_of_list = 3
length_of_sublists = 5
...
output = [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
I tried various times but I just can't understand how to do it.
Thank you for your help guys!
Edit: I include my code as asked! It clearly doesn't work as the output is nested lists. I'm sorry if I broke some rules, I'm new here :)
length_of_list = 3
length_of_sublist = 5
for i in range(length_of_list):
list = []
for j in range(1, length_of_sublist+1):
list.append(j)
list.append(list)
print(list)
[1, 2, 3, 4, 5, [1, 2, 3, 4, 5, [1, 2, 3, 4, 5]]]
If you want to create a nested list, consider using a nested list comprehension:
>>> length_of_list = 3
>>> length_of_sublists = 5
>>> [[i for i in range(1, length_of_sublists + 1)] for j in range(length_of_list)]
[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
I don't know what you need this for, but here is your solution
lenght_of_list = 3
length_of_sublists = 5
output = []
for i in range(length_of_list):
sub_list = []
for j in range(length_of_sublists):
sub_list.append(j+1)
output.append(sub_list)
You should try yourself. It will definitively help you if you try out many possible approaches.
You don't need a loop for this. Just break down this one liner. You will get this.
>>> [list(range(1, length_of_sublists+1))] * length_of_list
[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
Be careful when the item being repeated is a list. The list will not be cloned: all the elements will refer to the same list!
>>> output[0][0] = 9
>>> output
[[9, 2, 3, 4, 5], [9, 2, 3, 4, 5], [9, 2, 3, 4, 5]]
I am breaking my head around this small issue which I am sure can (and should) be solved recursively.
# split list in sublists based on length of first element.
list = [3, 1, 2, 3, 4, 1, 2, 3, 4]
#* #*
# *number of elements of the sublist
It is better shown than explained, the above should result to:
[[1, 2, 3], [1, 2, 3, 4]]
The lists I am processing always respect this logic, the first element is always the length of the following n elements.
EDIT:
Based on some of the suggestions, I simply added a yield to get it done lazily.
def split(ls):
"""
func that given a list extracts sub lists with the length indicated by the first element
[2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4] => [[1, 2], [1, 2, 3], [1, 2, 3, 4]]
"""
res = []
while ls:
dim = ls[0]
yield ls[1:dim + 1]
ls = ls[dim + 1:]
return res
>>> list(split([2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4]))
[[1, 2], [1, 2, 3], [1, 2, 3, 4]]
Simple slicing will do:
>>> a = [3, 1, 2, 3, 4, 1, 2, 3, 4]
>>> c = []
>>> while len(a) :
... b = a[0]
... c.append( a[1:b+1] )
... a = a[b+1:]
...
>>> c
[[1, 2, 3], [1, 2, 3, 4]]
Here is a way to achieve what you want:
numbers = [3, 1, 2, 3, 4, 1, 2, 3, 4]
result = []
def split_list(list_):
first = list_.pop(0)
result.append(list_[:first])
if len(list_[first:]) > 0:
split_list(list_[first:])
split_list(numbers)
print(result)
You can use itertools.islice here.
>>> from itertools import islice
>>> lst = [3, 1, 2, 3, 4, 1, 2, 3, 4]
>>> def chunks(lst):
... t=iter(lst)
... c=next(t,None)
... while c:
... yield list(islice(t,None,c))
... c=next(t,None)
...
>>> list(chunks(lst))
[[1, 2, 3], [1, 2, 3, 4]]
I've edited my answer as inspired by someone else's in this thread. This doesn't consume the original array and uses recursion instead of looping.
numbers = [3, 1, 2, 3, 4, 1, 2, 3, 4, 3,1,1,1,1]
def do_take(numbers: []):
result = []
to_take = numbers[0]
result.append(numbers[1:to_take + 1])
if len(numbers) > to_take:
result.append(do_take(numbers[to_take + 1:]))
return result
print(do_take(numbers))
print(numbers)
Results in the following output:
# python /tmp/breakup.py
[[1, 2, 3], [[1, 2, 3, 4], [[1, 1, 1], [[]]]]]
[3, 1, 2, 3, 4, 1, 2, 3, 4, 3, 1, 1, 1, 1]
Not to be confused with this question in Stackoverflow.
I have a list called a = [2, 3, 4, 1]
I have some function say func(), which is as follows:
def func(a):
o = []
n = len(a)
for i in range(n):
x=a[:]
x[i],x[(i+1)%n] = x[(i+1)%n],x[i]
o.append(x)
return o
and func(a) produces another list as follows:
[[3, 2, 4, 1], [2, 4, 3, 1], [2, 3, 1, 4], [1, 3, 4, 2]]
Now I want to map the output list to the list from which it is generated. So, how to generate a dictionary in the following format:
a : o
key : value1, value2........last value
[2, 3, 4, 1] : [3, 2, 4, 1], [2, 4, 3, 1], [2, 3, 1, 4], [1, 3, 4, 2]
Keys in a dictionary cannot be mutable type. You can have a tuple instead. That is
(2, 3, 4, 1) : [3, 2, 4, 1], [2, 4, 3, 1], [2, 3, 1, 4], [1, 3, 4, 2]
This can be done as
def func(a):
o = []
n = len(a)
for i in range(n):
x=a[:]
x[i],x[(i+1)%n] = x[(i+1)%n],x[i]
o.append(x)
return {tuple(a):o}
For example func([2,3,4,1]) will now return
{(2, 3, 4, 1): [[3, 2, 4, 1], [2, 4, 3, 1], [2, 3, 1, 4], [1, 3, 4, 2]]}
Also note: according to documentation :
The only types of values not acceptable as keys are values containing
lists or dictionaries or other mutable types that are compared by
value rather than by object identity, the reason being that the
efficient implementation of dictionaries requires a key’s hash value
to remain constant
POST COMMENT EDIT
You can access the keys directly usin [] notation.
E.g:
l = [2,3,4,1]
a = func(l)
print (a[tuple(l)])
This will print the list of values.
Or you can loop through the entire dictionary
for i in a.items():
for j in i:
print (j)
This will print
[3, 2, 4, 1]
[2, 4, 3, 1]
[2, 3, 1, 4]
[1, 3, 4, 2]
I have a list of lists like this:
i = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
I would like to get a list containing "unique" lists (based on their elements) like:
o = [[1, 2, 3], [2, 4, 5]]
I cannot use set() as there are non-hashable elements in the list. Instead, I am doing this:
o = []
for e in i:
if e not in o:
o.append(e)
Is there an easier way to do this?
You can create a set of tuples, a set of lists will not be possible because of non hashable elements as you mentioned.
>>> l = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
>>> set(tuple(i) for i in l)
{(1, 2, 3), (2, 4, 5)}
i = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
print([ele for ind, ele in enumerate(i) if ele not in i[:ind]])
[[1, 2, 3], [2, 4, 5]]
If you consider [2, 4, 5] to be equal to [2, 5, 4] then you will need to do further checks
You can convert each element to a tuple and then insert it in a set.
Here's some code with your example:
tmp = set()
a = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
for i in a:
tmp.add(tuple(i))
tmp will be like this:
{(1, 2, 3), (2, 4, 5)}
Here's another way to do it:
I = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
mySet = set()
for j in range(len(I)):
mySet = mySet | set([tuple(I[j])])
print(mySet)