How to find length of a multi-dimensional list? - python

How do you find the length of a multi-dimensional list?
I've come up with a way myself, but is this the only way to find the number of values in a multi-dimensional list?
multilist = [['1', '2', 'Ham', '4'], ['5', 'ABCD', 'Foo'], ['Bar', 'Lu', 'Shou']]
counter = 0
for minilist in multilist:
for value in minilist:
counter += 1
print(counter)
I'm pretty sure there is a much simpler way to find the length of a multi-dimensional list, but len(list) does not work, as it only gives the number of lists inside. Is there a more efficient method than this?

How about:
sum(len(x) for x in multilist)

Alternative to #mgilson's solution
sum(map(len, multilist))

If you want the number of items in any n-dimensional list then you need to use a recursive function like this:
def List_Amount(List):
return _List_Amount(List)
def _List_Amount(List):
counter = 0
if isinstance(List, list):
for l in List:
c = _List_Amount(l)
counter+=c
return counter
else:
return 1
This will return the number of items in the list no matter the shape or size of your list

Another alternative (it's this or watch missed math lectures...)
def getLength(element):
if isinstance(element, list):
return sum([getLength(i) for i in element])
return 1
This allows different degrees of 'multi-dimensionality' (if that were a word) to coexist.
eg:
>>> getLength([[1,2],3,4])
4
Or, to allow different collection types
def getLength(element):
try:
element.__iter__
return sum([getLength(i) for i in element])
except:
return 1
eg:
>>> getLength([ 1, 2, (1,3,4), {4:3} ])
6
>>> getLength(["cat","dog"])
2
(Noting that although strings are iterable, they do not have the __iter__ method-wrapper and so will not cause any issues...)

Related

Python find all the different choices from list of list

I want to get all the different choices from a list of lists in python. for example, take a list like,
list=[[a,b,c],[a,d,e]]
I just want to select choices from one at each list and get all the possible different selections.
so above list possible choices look like,
[a,a]
[a,d]
[a,e]
[b,a]
[b,d]
[b,e]
[c,a]
[c,d]
[c,e]
without using any external library, how can I do this?
Easiest to implement with a recursive generator.
def yield_combos(lst):
if lst:
for el in lst[0]:
for combo in yield_combos(lst[1:]):
yield [el] + combo
else:
yield []
lst = [['a','b','c'], ['a','d','e']]
for combo in yield_combos(lst):
print(combo)
If you prefer the output as a list, you can always convert it into one:
print(list(yield_combos(lst)))
Minor notes:
I've called the variable lst where the question uses list; it's not a good idea to override a builtin, and in this case doing so would prevent the call to list from working.
I've set some string values in the caller for sake of a self-contained program (the question had a in place of 'a', etc).
The simplest way to do this is with two functions
def funcA(x, arr):
return [(x,c) for c in arr]
def funcB(arr1, arr2):
ans = []
for x in arr1:
ans.extend(funcA(x, arr2))
return ans
Call it whichever way to need:
funcB(your_list[0], your_list[1])
The most pythonic way is with itertools
you can simply use product from the itertools library like so:
my_list = [[a,b,c],[a,d,e]]
# will contain: [(a,a), (a,d)...]
all_combinations = list(itertools.product(*my_list))
The "*" unpacks the list into the lists it contains, its like writing:
# will contain: [(a,a), (a,d)...]
list(itertools.product([a,b,c],[a,d,e]))
It is worth mentioning that this works for any number of sublists.
my_list = [[a,b,c],[a,d,e], [1,2,3]]
# will contain: [(a,a,1), (a,a,2)...]
all_combinations = list(itertools.product(*my_list))
Hope that helps
you could use generators,
perm = [(i,j) for i in list[0] for j in list[1]]
furthermore if you could convert this into a generator object, if you memory concerns,
perm = ((i,j) for i in list[0] for j in list[1]])
I was told you have n lists and want to permutate all of them,
you can use a while loop
while(len(list)>1):
a = list.pop()
b = list.pop()
list.append([(i, j) for i in a for j in b])
or make a recursive function. Do note, that the answer will be list[0] and not list itself.
l=[['a','b','c'],['a','d','e']]
def combinations(L, tmp=None):
if tmp is None:
tmp = []
if L==[]:
print (tmp)
else:
for i in L[0]:
product(L[1:], tmp+[i])
combinations(l)
Does this help?

size of a whole list containing tuple [duplicate]

This question already has answers here:
How do I make a flat list out of a list of lists?
(34 answers)
Closed 6 years ago.
I have a list made of tuple
liste_groupe=((image1, image2, image6),(image5, image4, image8, image7, image3, image9))
and i would like to have the number of element of all the tuple ie here the result would be 9
I have tried len(liste_groupe) but it gives me 2.
So what code should I write in order to have the number of all the element of all the tuples in a list ?
There is no need to flatten the list in order to find the total length, and there is no need to use recursion if you already know the list is a simple 2D structure. This is all you need:
sum(map(len, liste_groupe))
Flatten a tuple of tuples into a list,
>>> liste_groupe=(('image1', 'image2', 'image6'),('image5', 'image4', 'image8', 'image7', 'image3', 'image9'))
>>> l = [item for t in liste_groupe for item in t]
>>> len(l)
9
# Or use itertools.chain
>>> import itertools
>>> l = list(itertools.chain(*liste_groupe))
>>> len(l)
9
If you only care about the number of elements,
>>> count = sum([len(t) for t in liste_groupe])
>>> count
9
You can follow a recursive approach:
def tuple_length( t ):
if type(t) != tuple:
return 1
length = 0
for element in t:
length += tuple_length( element )
return length
Now, tuple_length(liste_groupe) will return 9 as expected.
Recursion could accomplish this for you. With the following function the size of an n-dimensional tuple or list could be counted.
def calculate_size(data_set, size=0):
for i in data_set:
if isinstance(i, tuple) or isinstance(i, list):
size += calculate_size(i)
else:
size += 1
return size
Will work for a single nested list. For deeper or irregularly nested lists, you'll need a recursive function that uses chain.
from itertools import chain
cnt = len(list(chain.from_iterable(list_group)))

Python: Get first element of list potentially containing sublists

I'm looking for the first element of a Python list potentially containing either numbers (integer or float), or many levels of nested sublists containing the same. In these examples, let's suppose I am always looking for the number '1'. If the list contains no sublists, we have:
>>> foo = [1,2,3]
>>> foo[0]
1
If the list contains one sublist, and I know this information, I can again obtain 1 with
>>> foo = [[1,2],[3,4]]
>>> foo[0][0]
1
Similarly if the first element of my list is a list containing a list:
>>> foo = [[[1,2],[3,4]],[[5,6],[7,8]]]
>>> foo[0][0][0]
1
Is there a general way to get the first integer or float in foo, without resorting to calling a function recursively until drilling down to a value of foo[0] that is no longer a list?
There shouldn't be any need for recursion. Assuming that you are always working with lists and ints, this should work perfectly well for you.
foo = [[[1,2],[3,4]],[[5,6],[7,8]]]
result = None
while True:
try:
result = foo[0]
except TypeError:
break
Unlike the other answers, this asks for forgiveness rather than for permission, which is a bit more Pythonic.
If you really want to be Pythonic, you could define a function like as follows. However, this would admittedly be overkill given your specification.
def first_scalar(foo):
result = None
while True:
try:
result = next(iter(foo))
except TypeError:
return result
Note that it returns None if the argument is not an iterable. The same applies for the first segment of code.
Note that this doesn't work if the if the deepest "left-most" child list is empty. To account for this, you'll need to totally flatten the list.
def _flatten(foo):
try:
for item in foo:
yield from flatten(foo)
except TypeError:
yield foo
def flatten(foo):
for item in foo:
yield from _flatten(foo)
def first_scalar(foo):
return next(flatten(foo))
Note that the above must be written in at least Python 3.3.
The following code is for earlier versions of Python.
def _flatten(foo):
try:
for item in foo:
for subitem in _flatten(foo):
yield subitem
except TypeError:
yield foo
def flatten(foo):
for item in foo:
for subitem in _flatten(foo):
yield subitem
The general-case answer for this is "Fix your data structure." Lists are supposed to be homogeneous, e.g. every element of the list should have the same type (be that int or list of ints or list of lists of ints or etc).
The special case here would be to recurse until you find a number and return it.
def foo(lst):
first_el = lst[0]
if isinstance(first_el, (float, int)):
return first_el
else:
return foo(first_el)
create a simple, recursive function:
>>> def getFirst(l):
return l[0] if not isinstance(l[0],list) else getFirst(l[0])
>>> getFirst([1,2,3,4])
1
>>> getFirst([[1,2,3],[4,5]])
1
>>> getFirst([[[4,2],12,[1,3]],1])
4
this will return l[0] if l[0] is anything but a list. else, it will return the first item of l[0] recursively
You can just "dive in", without any recursion:
lst = [[1, 2], [3, 4]]
first = lst
while isinstance(first, list):
first = first[0]
If you really want to avoid any loops or recursion, there is an ugly workaround. Transform the list to a string and then remove the list-specific chars:
','.join(map(str,foo)).replace('[','').replace(']','').replace(' ','').split(',')
Of course it only works if the list is composed by strings or integers. If the objects in the list are custom, you would have to transform them to string. But, since there is an unknown number of sublists, you would have to use recursion, so using this workaround wouldn't make sense.
Another thing, maybe the elements of the list and sublists have the same chars as the list-specific ones, such as '[' or ',', so that would also be a problem.
In short, this is a bad workaround that only works for sure if the list and sublists are composed of numbers. Otherwise, using some kind of recursion is most probably necessary.

How do I find out how many objects are in a list

basically what the title says. I want to be able to find out how many objects a list contains. Maybe my Google-fu is failing me or my terminology is wrong.
len(s)
Return the length (the number of items) of an object. The argument may be a sequence (string, tuple or list) or a mapping (dictionary).
>>> l = [1, 2, 3]
>>> len(l)
3
Check out the len built-in function:
len(someList)
http://docs.python.org/library/functions.html#len
a = ['1', '2', '3']
print len(a)
This wiil print:
3

Python: finding an element in a list [duplicate]

This question already has answers here:
Finding the index of an item in a list
(43 answers)
Closed 9 years ago.
What is a good way to find the index of an element in a list in Python?
Note that the list may not be sorted.
Is there a way to specify what comparison operator to use?
From Dive Into Python:
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.index("example")
5
If you just want to find out if an element is contained in the list or not:
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> 'example' in li
True
>>> 'damn' in li
False
The best way is probably to use the list method .index.
For the objects in the list, you can do something like:
def __eq__(self, other):
return self.Value == other.Value
with any special processing you need.
You can also use a for/in statement with enumerate(arr)
Example of finding the index of an item that has value > 100.
for index, item in enumerate(arr):
if item > 100:
return index, item
Source
Here is another way using list comprehension (some people might find it debatable). It is very approachable for simple tests, e.g. comparisons on object attributes (which I need a lot):
el = [x for x in mylist if x.attr == "foo"][0]
Of course this assumes the existence (and, actually, uniqueness) of a suitable element in the list.
assuming you want to find a value in a numpy array,
I guess something like this might work:
Numpy.where(arr=="value")[0]
There is the index method, i = array.index(value), but I don't think you can specify a custom comparison operator. It wouldn't be hard to write your own function to do so, though:
def custom_index(array, compare_function):
for i, v in enumerate(array):
if compare_function(v):
return i
I use function for returning index for the matching element (Python 2.6):
def index(l, f):
return next((i for i in xrange(len(l)) if f(l[i])), None)
Then use it via lambda function for retrieving needed element by any required equation e.g. by using element name.
element = mylist[index(mylist, lambda item: item["name"] == "my name")]
If i need to use it in several places in my code i just define specific find function e.g. for finding element by name:
def find_name(l, name):
return l[index(l, lambda item: item["name"] == name)]
And then it is quite easy and readable:
element = find_name(mylist,"my name")
The index method of a list will do this for you. If you want to guarantee order, sort the list first using sorted(). Sorted accepts a cmp or key parameter to dictate how the sorting will happen:
a = [5, 4, 3]
print sorted(a).index(5)
Or:
a = ['one', 'aardvark', 'a']
print sorted(a, key=len).index('a')
how's this one?
def global_index(lst, test):
return ( pair[0] for pair in zip(range(len(lst)), lst) if test(pair[1]) )
Usage:
>>> global_index([1, 2, 3, 4, 5, 6], lambda x: x>3)
<generator object <genexpr> at ...>
>>> list(_)
[3, 4, 5]
I found this by adapting some tutos. Thanks to google, and to all of you ;)
def findall(L, test):
i=0
indices = []
while(True):
try:
# next value in list passing the test
nextvalue = filter(test, L[i:])[0]
# add index of this value in the index list,
# by searching the value in L[i:]
indices.append(L.index(nextvalue, i))
# iterate i, that is the next index from where to search
i=indices[-1]+1
#when there is no further "good value", filter returns [],
# hence there is an out of range exeption
except IndexError:
return indices
A very simple use:
a = [0,0,2,1]
ind = findall(a, lambda x:x>0))
[2, 3]
P.S. scuse my english

Categories

Resources