Summing using Inline for loop vs normal for loop - python

I'm trying to sum a list named mpg with the entry 'cty' (converted from a dictionary).
Sample data:
[{'': '1', 'trans': 'auto(l5)', 'drv': 'f', 'cty': '18'}, {'': '2', 'trans': 'manual(m5)', 'drv': 'f', 'cty': '21'}]
I tried 2 ways of doing this:
This gives the error that float object is not iterable.
for d in mpg:
sum(float(d['cty']))
No problem with this one.
sum(float(d['cty']) for d in mpg)
I understand that float objects are not iterable but isn't the 2nd method just an example of list comprehension of the 1st one?
Why does the second option work but not the first?

sum() takes an iterable as an argument and sums all items of that iterable. A simple float or integer is not a list and therefore not iterable.
In example 1, you iterate through each item of your list of dictionaries, but then only pass a single float (the float value of the current dictionary) to your function, resulting in sum(123), which then returns an error.
In example 2, you first iterate through your whole list of dictionaries and extract the values you need into a new list. If you stored float(d['cty']) for d in mpg in a new variable, it would create a list. If you now pass that list, the function results in sum([123, 456, 789]), which returns the desired value.

The second one works because the list comprehension constructs a list prior to trying to evaluate the sum, but the first way tries to pass float(d['cty']) to the sum. But that's just a float rather than an iterable (which is what sum needs). See this modification of the first way:
lst = []
for d in mpg:
lst.append(float(d['cty']))
sum(lst)

Two ways to solve the problem:
1.
i = 0
for d in mpg:
i += float(d['cty'])
x = sum([float(d['cty']) for d in mpg])

Related

Is there a way to insert values into a list of tuple in Python?

I have a empty list of tuple and I wish to enter values inside that tuple.
The desired output is :
lst = [()] --> lst = [(1,2,'string1','string2',3)]
A tuple is, by definition, unchangable.
You may want to replace that tuple with a new one like this:
lst = [()]
lst[0] = ("item1", "item2")
In this way you are replacing the origina tuple with a new one with the desired items. If the tuple is not empty you can do:
lst[0] = (*lst[0], "new item")
Here you are unpacking the values of the old tuple (*lst[0] is equal to "item1", "item2" in this example) and adding new items.
Note that if you are working with variable data maybe tuple is not the best data structure to use in this case.
you can't, A tuple is a collection that is ordered and immutable.
though, you can create a new tuple with the same name

Problem with comparing two items in a list of lists

I have this list
zipped_values = [(3.0, 4.242640687119285), (3.605551275463989, 3.1622776601683795), (5.0, 3.1622776601683795), (4.123105625617661, 4.47213595499958), (5.0, 4.0), (5.830951894845301, 7.810249675906654), (5.0990195135927845, 5.385164807134504), (7.0710678118654755, 8.06225774829855), (7.0710678118654755, 7.280109889280518), (8.06225774829855, 8.246211251235321)]
what I am trying to do is compare each item within the lists to each other (within the same list), to find out what the minimum is. In the first case, it would be 3.0, in the second, it would be 3.1.
Now what I am trying to do is, if the minimum is the first element, assign that element (3.0) to a dictionary key named M1, and if the minimum is the second element, assign that element to a dictionary key named M2.
This is what I've come up with:
for jk in zipped_value:
for n in jk:
if zipped_value[0][n] < zipped_value[0][n+1]:
dictionary["M1"].append(zipped_value[0][n])
But it gives me this error: TypeError: tuple indices must be integers or slices, not float
What do I do?
You don't need the inner loop. jk is the tuple, you just need to compare jk[0] with jk[1]. You can simplify this by unpacking to two variables when looping.
for a, b in zipped_values:
if a < b:
dictionary["M1"].append(a)
else:
dictionary["M2"].append(b)
Your inner for loop is iterating over the tuple, so the value of n is actually the floats in your tuple. Additionally, you will have problems with the append statement since it does not seem like you are initializing the dictionary values to be list type. Lastly, python allows you to unpack your tuples as you are iterative over them, making the code easier to read and comprehend rather than needing to use indices.
Try this:
from collections import defaultdict
dictionary = defaultdict(list)
for item1, item2 in zipped_value:
if item1 < item2:
dictionary["M1"].append(item1)
else:
dictionary["M2"].append(item2)
You are getting this error "TypeError: tuple indices must be integers or slices, not float" because in the
"for n in jk" the 'n' here is actually representing the float values in tuples and is not the index of tuple.
So,
if zipped_value[0][n] < zipped_value[0][n+1]:
dictionary["M1"].append(zipped_value[0][n])
is not correct indexing to access elements of tuples in a list.
You can modify your code to something below to get correct results:
for jk in zipped_values:
if jk[0] < jk[1]:
dictionary["M1"].append(jk[0])
else:
dictionary["M2"].append(jk[1])

Initialize a list using inline for loop

I am initializing my list object using following code.
list = [
func1(centroids[0],value),
func1(centroids[1],value),
....,
func1(centroids[n],value)]
I am trying to do it a more elegant way using some inline iteration. Following is the pseudo code of one possible way.
list = [value for value in func1(centroids[n],value)]
I am not clear how to call func1 in an iterative way. Can you suggest a possible implementation?
For a list of objects, Python knows how to iterate over it directly so you can eliminate the index shown in most of the other answers,
res = [func1(c, value) for c in centroids]
That's all there is to it.
A simple list comprehension consists of the "template" list element, followed by the iterator needed to step through the desired values.
my_list = [func1(centroids[0],value)
for n in range(n+1)]
Use this code:
list = [func1(centroids[x], value) for x in range(n)]
This is called a list comprehension. Put the values that you want the list to contain up front, then followed by the for loop. You can use the iterating variable of the for loop with the value. In this code, you set up n number(s) of variable(s) from the function call func1(centroids[x], value). If the variable n equals to, let's say, 4, list = [func1(centroids[0], value), func1(centroids[0], value), func1(centroids[0], value), func1(centroids[0], value)] would be equal to the code above

Why the size of list reduced after being converted to dictionary in Python?

I have a list which is composed of tuples where the employee is unique:
my_list = [(Decimal('679.666666'), 'Employee1'),
(Decimal('792.000000'), 'Employee2'),...]
and I've made it to dictionary by using:
new_dict = dict(my_list)
However, I found the size of the object has been reduced after it is converted to dictionary (len(my_list) = 404, len(new_dict) = 353)
I have no idea why this is happening. Can anyone let me know what is wrong?
Many thanks.
When you convert a list of tuples to a dictionary, the first value of the tuple is taken as the key in the dictionary, and the second value as the value.
Most probably there are tuples where the first value is equal to the first value of some other tuples, and hence in those cases the values get overwritten by the tuples that come later. And hence this would be the reason why the dictionary size is lesser than the list size.
Example to show this -
>>> l = [(1,2),(2,3),(1,4)]
>>> dict(l)
{1: 4, 2: 3}

Indexing According to Number in the Names of Objects in a List in Python

Apologies for my title not being the best. Here is what I am trying to accomplish:
I have a list:
list1 = [a0_something, a2_something, a1_something, a4_something, a3_something]
i have another list who entries are tuples including a name such as :
list2 = [(x1,y1,z1,'bob'),(x2,y2,z2,'alex')...]
the 0th name in the second list corresponds to a0_something and the name in the 1st entry of the second list corresponds to a1_something. basically the second list is in the write order but the 1st list isnt.
The program I am working with has a setName function I would like to do this
a0_something.setName(list2[0][4])
and so on with a loop.
So that I can really just say
for i in range(len(list1)):
a(i)_something.setName(list2[i][4])
Is there anyway I can refer to that number in the a#_something so that I can iterate with a loop?
No.
Variable names have no meaning in run-time. (Unless you're doing introspection, which I guarantee you is something you should not be doing.)
Use a proper list such that:
lst = [a0_val, a1_val, a2_val, a3_val, a4_val]
and then address it by lst[0].
Alternatively, if those names have meanings, use a dict where:
dct = {
'a0' : a0_val,
'a1' : a1_val,
# ...
}
and use it with dct['a0'].
The enumerate function lets you get the value and the index of the current item. So, for your example, you could do:
for i, asomething in enumerate(list1):
asomething.setName(list2[i][3])
Since your list2 is length 4, the final element is index 3 (you could also use -1)

Categories

Resources