Finding the number of lists in a tuple - python

I have a function that takes two inputs, both tuples, and checks to ensure they are the same size before continuing. I am having issues in trying to calculate the length of each tuple.
Examples:
tupA = ([1,2,3,4],[11,22,33,44])
tupB = ([1,2],[3,4],[5,6])
tupC = ([1,2,3,4,5,6,7,8,9])
When I take the length of each object it returns:
len(tupA) = 2
len(tupB) = 3
len(tupC) = 9
Is there an easy way to have the len(tupC) return 1? I found a workaround by adding a comma:
tupD = ([1,2,3,4,5,6],)
len(tupD) = 1
But I don't want to force the user to have to add the comma. Is there a better way to do this?

For such data
tupA = ([1,2,3,4],[11,22,33,44])
tupB = ([1,2],[3,4],[5,6])
tupC = ([1,2,3,4,5,6,7,8,9])
last one is not tuple, as you might check
print(type(tupC)) #prints <class 'list'>
You might check if variable is of given type using isinstance function, you could therefore create own function
def mylen(x):
if isinstance(x,list):
return 1
else:
return len(x)
Which will give 1 for your tupC, 3 for your tupB and 2 for your tupA.

You would have to have the comma to make the len work as you expect, as mentioned in the docs
A tuple with one item is constructed by following a value with a comma.
The only benefit of a tuple would be to make it immutable,
but if you use lists, there is no problem.
>>> listA = [[1,2,3,4],[11,22,33,44]]
>>> listB = [[1,2],[3,4],[5,6]]
>>> listC = [[1,2,3,4,5,6,7,8,9]]
>>> len(listA)
2
>>> len(listB)
3
>>> len(listC)
1

As discussed in comments, tupC is not a tuple, it's a list with 9 elements. It's a tuple only when there is a trailing comma.
As a workaround, we can check if it's a list and return results accordingly:
def length_(tupl):
return 1 if isinstance(tupl, list) else len(tupl)
Usage:
>>> tupA = ([1,2,3,4],[11,22,33,44])
>>> tupB = ([1,2],[3,4],[5,6])
>>> tupC = ([1,2,3,4,5,6,7,8,9])
>>> length_(tupA)
2
>>> length_(tupB)
3
>>> length_(tupC)
1

Notice that tupC is actually a list, not a tuple:
>>> tupA = ([1,2,3,4],[11,22,33,44])
>>> tupB = ([1,2],[3,4],[5,6])
>>> tupC = ([1,2,3,4,5,6,7,8,9])
>>> type(tupA), type(tupB), type(tupC)
(<class 'tuple'>, <class 'tuple'>, <class 'list'>)
If you still insist on keeping things as tuples of lists instead of lists of lists, and don't want to add the comma, you could define your own function to handle this:
>>> def newlength(x):
... if type(x) == list:
... return 1
... return len(x)
...
>>> print(newlength(tupA))
2
>>> print(newlength(tupB))
3
>>> print(newlength(tupC))
1
EDIT: Kudos to Daweo for beating me to an almost identical answer by a couple of minutes!

Related

Access elements in a Python tuple

I have a tuple like this:
('TRM',)
I would like to extract the string only from this tuple.
I did the following and it works but just thinking if there is a better way to do that.
>>> b = [x for x in a]
>>> b
['TRM']
>>> for i in b:
... print(i)
...
TRM
>>>
This will help you
b = [x for x in a if type(x) == type("Str")]
print(b)
If you need to access a specific element of the tuple you can do it by index:
>>> a[0]
TRM
Not exactly sure what you're asking for but you could do:
for i in b:
if isinstance(i, str):
print(i)
and this will print
TRM
Edit: Now it checks whether an element is a string.

why __len__() give different output result for s = [] and s=[[]]?

code snippet:
>>>s = []
>>>len(s)
0
however:
>>>s = [[]]
>>>len(s)
1
I just declare two lists but did not assign any element, why len() give different output?
You did assign an element. Your second list contains another empty list:
>>> l = [[]]
>>> l
[[]]
>>> len(l)
1
>>> l[0]
[]
>>> len(l[0])
0
If it helps, break down what you did into two steps; create an empty list then create another list with just that one element:
>>> l1 = [] # empty
>>> len(l1)
0
>>> l2 = [l1] # one element
>>> l2
[[]]
>>> len(l2)
1
Other than that we have one more reference to the nested list, the outcome is exactly the same; an empty list contained within another list object.
You could add any number of empty lists inside an outer list; that doesn't make the outer list empty however:
>>> len([[], [], []])
3
because each of those empty lists contained in the outer list is still a separate object.
Note: use the len() built-in function, don't call the __len__ method directly. Python takes care of that detail for you.
If you wanted to know the total lengths of all contained lists, you could use:
sum(len(sub) for sub in outer)
or you could use:
not any(outer)
if you just wanted to know if all contained elements are 'empty' or otherwise considered false.
Demo:
>>> s = [[1, 2], [3, 4]] # not empty
>>> not any(s)
False
>>> sum(len(sub) for sub in s)
4
>>> s = [[], []] # all empty
>>> not any(s)
True
>>> sum(len(sub) for sub in s)
0
In one case you do have an element in your list : an empty list.
s = [[], []]
has two elements for example.
s = [[]]
has one element and
s = []
is empty
[] is an empty list, it has zero elements.
[[]] is a list with exactly one element, an empty list.
>>> for x in []:
... print(x)
...
>>> for x in [[]]:
... print(x)
...
[]
As your can see, the first for loop prints nothing, because there's nothing in []. The second for loop prints [], because there's [] inside [[]].
If you know the concept of sets from math, here's an analogy:
Let x = {} be the empty set. Then the set {x} contains one element (the empty set).
The second list indeed contains an element, which is an empty list.

What does 'x, y =' mean in python syntax? [duplicate]

This question already has answers here:
How are tuples unpacked in for loops?
(8 answers)
Closed 9 years ago.
I'm new to python and trying to work my way through http://yuji.wordpress.com/2011/06/22/python-imaplib-imap-example-with-gmail/ which has the following line:
result, data = mail.uid('search', None, "ALL") # search and return uids instead
Could someone explain this line?
Thank you.
It means that the function you have called returns an iterable, and the index 0 of the iterable is assigned to x and the index 1 is assigned to y. This is called tuple unpacking.
Eg)
>>> def func(a,b):
... return b,a
...
>>> a = 5
>>> b = 7
>>> a,b = func(a,b)
>>> a
7
>>> b
5
>>> x = func(a,b)
>>> x
(5, 7)
Edit to show that returning multiple values, they are packed as tuple by default and then unpacked at the other end. Since there is only one variable x here, the tuple is assigned to x.
Simple function for swapping two variables(Just for an example) that answers your question
At least, as of python 2.7.x, the function will unpack a tuple of 2 arguments returned from a function. If it returns anything other than 2 arguments in the tuple, I believe it will throw an error if you try to unpack more than this. If it returns 3 arguments and you unpack 2, for example, you will get an exception.
For example:
def func(a):
return (a,a+1,a*2)
a,b,c = func(7)
print a,b
==> 7 8 # NOTE Values
a = func(3)
print a
==> (3, 4, 6) # NOTE: TUPLE
a,b = func(9)
print a,b
==> Exception - ValueError: too many values to unpack
This may be different in 3.0+.
The other answer, that "the function you have called returns an iterable" is a good one. That is what is happening in your specific example. This is what is called "unpacking" in python. The following are examples of unpacking and assignment related to your question:
>>> a,b = 1,2
>>> a
1
>>> b
2
>>> a,b,c = ['do', 're', 'mi']
>>> a
'do'
>>> b
're'
>>> c
'mi'
>>>
This is one of the pretty features of Python syntax. If I am not mistaken, it is also optimized - i.e. the fastest way to achieve the result.

a=list().append("hello") vs a=list(); a.append("hello") in python?

I have
try:
a = list().append('hello')
but a is NoneType
try:
b = list()
b.append('hello')
and b is a list type
I think list() returns a list object, and list().append('hello') will use the return list to do append, but why is the value of a None?
list() does indeed return an empty list ([]), but the append method operates on a list in-place - it changes the list itself, and doesn't return a new list. It returns None instead.
For example:
>>> lst = []
>>> lst.append('hello') # appends 'hello' to the list
>>> lst
['hello']
>>> result = lst.append('world') # append method returns None
>>> result # nothing is displayed
>>> print result
None
>>> lst # the list contains 'world' as well now
['hello', 'world']
a = list().append('hello')
The above line, would create a new list, then invoke the append() method, and just store the return code of append() to the variable a. And since the value is None, it just means that the append() method does not have a return value.
To confirm this, you could try this:
>>> a = list()
>>> result = a.append('hello')
>>> print a
['hello']
>>> print result
None
You already got the answer to your question, but I'd just point out that the best way to do what you're trying to do is neither. It should be:
a = [ 'hello' ]

how to know the number of iterables in a generator in python

I have the following code
>>> x = ['a','b','c','d','e']
>>> def test_yield(lst):
... for el in lst:
... yield el
...
>>> var = test_yield(x)
>>> var.next()
'a'
>>> var.next()
'b'
>>> var.next()
'c'
>>> var.next()
'd'
>>> var.next()
'e'
how can I know the length of iterables (in this case the length of the list) from the generator.
In my real case, I do not have the exact list. I have that from generator. simply put, I would like to know the number of iterables in var after my second var.next() or so.
You can not. Iterators can be infinite.
def test_yield():
count = 1
while True:
count += 1
yield count
If you know that your iterator is not infinite (see #unutbu's answer), you can put put the results in a list first, and then get the length:
stuff = list(test_yield(x))
print(len(stuff))

Categories

Resources