finding the index of a variable in a nested list - python

def total_sales(sales_table, product):
if product in sales_table[0]:
return sum(list(zip(*sales_table[1:]))[sales_table[0].index(product)])
return 'Product not found'
Hi could someone explain 1. what the * is doing after the zip() and 2. why there is no comma or break between the two elements in the sum()
many thanks

At first there the * is for unpacking the list next to it, you can check the python syntax for the * and learn how it's used, and the other question u had, There are no comma in sum() because of it have a list() inside it, And sum() takes a list at sums it's up and return the sum of it.

To iterate through nested lists, I usually use For loops.
Check this site for more info about ways to iterate through lists in python:
https://www.geeksforgeeks.org/iterate-over-a-list-in-python/
To get the index of a variable in a list (after iterating correctly through all your nested lists), use .index(element, start, end). This will return the index of the desired element you are searching for.
For more information about .index()
https://www.programiz.com/python-programming/methods/list/index
The zip() function returns a zip object, which is an iterator of tuples where the first item in each passed iterator is paired together, and then the second item in each passed iterator are paired together etc.
If the passed iterators have different lengths, the iterator with the least items decides the length of the new iterator.
https://realpython.com/python-zip-function/#:~:text=Python's%20zip()%20function%20is,%2C%20sets%2C%20and%20so%20on.
The sum(iterable, start) function returns a number, the sum of all items in an iterable.
https://www.programiz.com/python-programming/methods/built-in/sum
Example:
numbers = [2.5, 3, 4, -5]
# start parameter is not provided
numbers_sum = sum(numbers)
print(numbers_sum)
# start = 10
numbers_sum = sum(numbers, 10)
print(numbers_sum)
# 4.5
# 14.5
The * can also be used for unpacking the containers. The easiest example is that we have data in the form of a list, tuple or dict, and a function take variable arguments:
from functools import reduce
primes = [2, 3, 5, 7, 11, 13]
def product(*numbers):
p = reduce(lambda x, y: x * y, numbers)
return p
product(*primes)
# 30030
product(primes)
# [2, 3, 5, 7, 11, 13]
Because the product() take the variable arguments, we need to unpack the our list data and pass it to that function. In this case, if we pass the primes as *primes, every elements of the primes list will be unpacked, then stored in list called numbers. If pass that list primes to the function without unpacking, the numbers will has only one primes list not all elements of primes.

Related

How do I sum the first two values in each tuple in a list of tuples in Python?

I searched through stackoverflow but couldn't find an answer or adapt similar codes, unfortunately.
The problem is that I have a list of tuples:
tupl = [(5,3,33), (2,5,2), (4,1,7)]
and I should use list comprehension to have this output:
[8,7,5]
The code that I wrote is a bit dump and is:
sum_tupl = []
tupl = [(5,3,33), (2,5,2), (4,1,7)]
sum_tupl = [tupl[0][0]+tupl[0][1] for tuple in tupl]
sum_tupl
but instead of doing what I want it to do, it returns
[8,8,8]
which is the sum of the first couple executed three times.
I tried using a variant:
tupl = [(5,3,33), (2,5,2), (4,1,7)]
sum_tupl = [sum(tupl[0],tupl[1]) for tuple in tupl]
sum_tupl
(which is missing something) but to no avail.
Note: When you're beginning python, it's much easier to use loops instead of list comprehensions because then you can debug your code more easily, either by using print() statements or by stepping through it using a debugger.
Now, on to the answer:
When you do for x in y, with a list y, the individual items go in x. So for your code for tuple in tupl, you shouldn't use tupl because that is the entire list. You need to use the individual item in the list, i.e. tuple.
Note that it's not a good idea to name a variable tuple because that's already a builtin type in python.
You need:
tupl = [(5,3,33), (2,5,2), (4,1,7)]
sum_tupl = [t[0]+t[1] for t in tupl]
Which gives the list
sum_tupl: [8, 7, 5]
If you have more elements you want to sum, it makes more sense to use the sum() function and a slice of t instead of writing out everything. For example, if you wanted to sum the first 5 elements, you'd write
sum_tupl = [sum(t[0:5]) for t in tupl]
instead of
sum_tupl = [t[0]+t[1]+t[2]+t[3]+t[4] for t in tupl]
Each loop iteration you're accessing the first element of your tupl list, instead of using the current element. This is what you want:
sum_tupl = [t[0] + t[1] for t in tupl]
I prefer slicing:
>>> [x + y for x, y, *_ in tupl]
[8, 7, 5]
>>>

Pairwise multiplier list arguments Python

I'm trying to write a pairwise multiplier function which takes two arguments, both being lists. pairwise_multiply should return a new list with each of the elements in the two input lists multiplied together in a pairwise fashion. e.g.
result = pairwise_multiply([1, 2], [3, 4])
print(result)
> [3, 8]
This is my current function but I keep getting syntax errors:
def pairwise_multiply([l1], [l2]):
i = 0
while 1 <= len(l1):
lst = int(l1[i] * l2[i])
i = i + 1
return lst
In your code here -
def pairwise_multiply([l1], [l2]):
You don't need square brackets to pass lists as arguments. Replace it with -
def pairwise_multiply(l1, l2):
Another implementation, more pythonic would be to use list comprehension with zip -
[i*j for i, j in zip(l1, l2)]
What zip does is (from official documentation)-
Make an iterator that aggregates elements from each of the iterables.
Returns an iterator of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables. The iterator stops when the shortest input iterable is exhausted. With a single iterable argument, it returns an iterator of 1-tuples
There are some syntax and logic errors in this snippet.
def pairwise_multiply([l1], [l2]) As #FHTMitchell pointed out, you should cannot not use [...] when naming the arguments. This should be def pairwise_multiply(l1, l2)
while 1 <= len(l1) you mean i, not 1, right? Otherwise you will have an infinite loop. Also, since Python uses zero-based indexing, <= should become <.
You overwrite lst in every iteration. Your function will only return (if at all, see previous point) the result of the last multiplication.
Taking these into account, your code can be transformed to
def pairwise_multiply(l1, l2):
lst = []
i = 0
while i < len(l1):
lst.append(int(l1[i] * l2[i]))
i = i + 1
return lst
But it has many points of failure (for example, what if l1 and l2 are not the same length?), too long and not pythonic.
We can use zip and list comprehension like #ThatBird suggested in their answer.

Making a list comprehension for a dict within a list within a list

I need to create a list comprehension that extracts values from a dict within a list within a list, and my attempts so far are failing me. The object looks like this:
MyList=[[{'animal':'A','color':'blue'},{'animal':'B','color':'red'}],[{'animal':'C','color':'blue'},{'animal':'D','color':'Y'}]]
I want to extract the values for each element in the dict/list/list so that I get two new lists:
Animals=[[A,B],[C,D]]
Colors=[[blue,red],[blue,Y]]
Any suggestions? Doesn't necessarily need to use a list comprehension; that's just been my starting point so far. Thanks!
Animals = [[d['animal'] for d in sub] for sub in MyList]
Colors = [[d['color'] for d in sub] for sub in MyList]
Gives the desired result:
[['A', 'B'], ['C', 'D']]
[['blue', 'red'], ['blue', 'Y']] # No second 'red'.
What I have done here is take each sub-list, then each dictionary, and then access the correct key.
In a single assignment (with a single list comprehension, and the help of map and zip):
Colors, Animals = map(list,
zip(*[map(list,
zip(*[(d['color'], d['animal']) for d in a]))
for a in MyList]))
If you are fine with tuples, you can avoid the two calls to map => list
EDIT:
Let's see it in some details, by decomposing the nested comprehension.
Let's also assume MyList have m elements, for a total of n objects (dictionaries).
[[d for d in sub] for sub in MyList]
This would iterate through every dictionary in the sublists. For each of them, we create a couple with its color property in the first element and its animal property in the second one:
(d['color'], d['animal'])
So far, this will take time proportional to O(n) - exatly n elements will be processed.
print [[(d['color'], d['animal']) for d in sub] for sub in MyList]
Now, for each of the m sublists of the original list, we have one list of couples that we need to unzip, i.e. transform it into two lists of singletons. In Python, unzip is performed using the zip function by passing a variable number of tuples as arguments (the arity of the first tuple determines the number of tuples it outputs). For instance, passing 3 couples, we get two lists of 3 elements each
>>> zip((1,2), (3,4), (5,6)) #Prints [(1, 3, 5), (2, 4, 6)]
To apply this to our case, we need to pass array of couples to zip as a variable number of arguments: that's done using the splat operator, i.e. *
[zip(*[(d['color'], d['animal']) for d in sub]) for sub in MyList]
This operation requires going through each sublist once, and in turn through each one of the couples we created in the previous step. Total running time is therefore O(n + n + m) = O(n), with approximatively 2*n + 2*m operations.
So far we have m sublists, each one containing two tuples (the first one will gather all the colors for the sublist, the second one all the animals). To obtain two lists with m tuples each, we apply unzip again
zip(*[zip(*[(d['color'], d['animal']) for d in sub]) for sub in MyList]
This will require an additional m steps - the running time will therefore stay O(n), with approximatively 2*n + 4*m operations.
For sake of simplicity we left out mapping tuples to lists in this analysis - which is fine if you are ok with tuples instead.
Tuples are immutable, however, so it might not be the case.
If you need lists of lists, you need to apply the list function to each tuple: once for each of the m sublists (with a total of 2*n elements), and once for each of the 2 first level lists, i.e. Animals and Colors, (which have a total of m elements each). Assuming list requires time proportional to the length of the sequence it is applied to, this extra step requires 2*n + 2*m operations, which is still O(n).

creating recursive list length checker in python [duplicate]

This question already has answers here:
Flatten an irregular (arbitrarily nested) list of lists
(51 answers)
Closed 8 years ago.
I have a set Elements that have multiple other elements nested inside of them. I am trying to extract all of them through recursion since I don't know how many levels deep does the nesting go. To compare this to something more pythonic i would say imagine a list of elements. Each item on that list can either be a single value or another list of elements. Then for each sub-list there can be either a single value or more sub-lists. I want to go through all of them and pull out each element from all of the list until the last of sub-lists have nothing but single items on it.
lst = [1,[[2,3,4],[5,6,7]],[[8,9,10],[[11,12,13],[14,15,16]]],17,18]
for i in lst:
subElem = i.GetSubComponentIds()
if subElem.Count >= 1:
idsList.append(subElem)
for i in subElem:
subElem2 = i.GetSubComponentIds():
if subElem2.Count = >= 1:.... and so on
How would I set up a recursive function that would grab every element on a input list run a GetSubComponentIds() function on it (that either returns another list or nothing). if the return is a list then run the same function GetSubComponentsIds() on each item of that sublist until you get nothing in return. At the same time for those that returned nothing i want that Id appended. So if i used the lst from the example above i would end up with a list of all of the elements 1-18 (the only trick is that i donk know how many sub lists deep each element on the original list is).
As I understand it, you want to use recursion to extract the elements buried in some nested object. Here is one method:
def is_list(x):
# Replace this with an appropriate test for your type
return hasattr(x, 'index')
def recurse(lst):
if is_list(lst):
elements = []
for element in lst:
elements += recurse(element)
return elements
else:
return [lst]
Run on your sample list:
>>> recurse(lst)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
Please refer to following code working with regular lists:
def flattern(lst, res):
for elem in lst:
if isinstance(elem, list):
flattern(elem, res)
else:
res.append(elem)
Please update it to using your functions

How to "unzip" then slice and find max for elements in a list of lists in Python

I have a list of lists and need to find a way to find the max of the numerical portion of element [0] of each list. I know it'll involve slicing and finding max and think it'll involve the zip(*L) function but don't really know how to get there. For example, what I have is a list of lists that looks like this:
L = [['ALU-001', 'Aluminum', 50], ['LVM-002', 'Livermorium', 20], ['ZIN-003', 'Zinc', 30]]
and need to find the largest numerical portion (ex. 001) of the first elements.
You can do unzip using zip(*L), and since the numerical comparison is same as comparing alphabetically, so you don't have to convert the numerical part to int if the number have a fixed width.
>>> max([i.split('-')[1] for i in zip(*L)[0]])
'003'
zip is its own complement!
L = [['ALU-001', 'Aluminum', 50], ['LVM-002', 'Livermorium', 20], ['ZIN-003', 'Zinc', 30]]
zip(*L)[0]
#=> ('ALU-001', 'LVM-002', 'ZIN-003')
However, it's unnecessary to zip here. Instead, most python sort/max/etc. functions take a key argument:
max(L,key=lambda (a,b,c):int(a.split('-')[1]))
#=> ['ZIN-003', 'Zinc', 30]
The max function considers the value generated by applying key to each element of L.
max(int(subl[0].rsplit('-',1)[1]) for subl in L)
This will return 3. If you want to print '003', then you can do this:
print "%03d" %max(int(subl[0].rsplit('-',1)[1]) for subl in L)
Explanation:
As you seem to already know, max takes a list of numbers and returns the largest one. This is almost correct: max takes any interable and returns the largest element. A generator is an iterable and takes O(1) space as opposed to a list, which takes O(n) space.
You can also use a list comprehension to create a generator (called a generator comprehension), which is what I have done.
(int(subl[0].rsplit('-',1)[1]) for subl in L)
is the same as:
def myGen():
for subl in L:
elem = subl[0]
myNum = elem.rsplit('-', 1)
myNum = int(myNum)
yield myNum
max(myGen)
The subl iteration iterates over the sublists of L. subl[0] gets the 0th element of each sublist. We then call rsplit('-' ,1), which splits the string into two parts, at the occurrence of the first - from the end of the string; the splits are presented in a list. The 0th index of this list is what was on the left of the - and the 1th index is what was to the right. Since the number was on the right, we take subl[0].rsplit('-',1)[1].
At this point, we only have the string '003', which we want to turn into an int for the purposes of maxing. So we call int(subl[0].rsplit('-',1)[1]). And that's how this generates all the required numbers, which max then pulls the biggest one out of

Categories