Looping and appending to a list - python

def makelist():
list = []
initial = [0, 100]
a = 1
while a <= 10:
new_num = (initial[0] + initial[1])//2
if new_num%2 == 0:
initial[1] = new_num
else:
initial[0] = new_num
list.append(initial)
a += 1
return list
Why does the above code return:
[[43, 44], [43, 44], [43, 44], [43, 44], [43, 44], [43, 44], [43, 44], [43, 44], [43, 44], [43, 44]]
Rather than:
[[0, 50], [25, 50], [37, 50], [43, 50], [43, 46], [43,44], [43, 44], [43, 44], [43, 44], [43, 44]]
ie. The successive divisions rather than the final division 10 times over.
Thanks

First things first, NEVER name your variables with the builtin types names. In your case list. And your program doesnt work as expected, because
list.append(initial)
you are appending the reference to the same list again and again. At the end, all the elements in the list are pointing to the same list initial. To fix that, you can create a copy of initial like this and append it
list.append(initial[:])
Check this diagram out https://www.lucidchart.com/documents/edit/43c8-0c30-5288c928-a4fe-105f0a00c875. This might help you understand better.

Related

I need to figure out an automation sum op in my lists

I have this matrix, result of 4 lists:
results= [
[20, 20, 20, 60],
[35, 35, 20, 80],
[10, 10, 10, 30],
[40, 40, 40, 130]
]
The fourth element of each list is the result of the sum of the other elements (for instance in the first list: 20+20+20=60.
There are some errors in some lists that must be figured out with an automatic function. So it is not valid to replace manually the wrong element by another correct one such as: notas[3][3] = 120. I need an automation to run the operation with no errors.
You don't need to check the sum, just recompute it and set the result to the last item of the current list.
for r in results:
r[-1] = sum(r[:-1])
print(results)
# Output:
[[20, 20, 20, 60],
[35, 35, 20, 90],
[10, 10, 10, 30],
[40, 40, 40, 120]]

Count duplicate lists inside a list

lis = [ [12,34,56],[45,78,334],[56,90,78],[12,34,56] ]
I want the result to be 2 since number of duplicate lists are 2 in total. How do I do that?
I have done something like this
count=0
for i in range(0, len(lis)-1):
for j in range(i+1, len(lis)):
if lis[i] == lis[j]:
count+=1
But the count value is 1 as it returns matched lists. How do I get the total number of duplicate lists?
Solution
You can use collections.Counter if your sub-lists only contain numbers and therefore are hashable:
>>> from collections import Counter
>>> lis = [[12, 34, 56], [45, 78, 334], [56, 90, 78], [12, 34, 56]]
>>> sum(y for y in Counter(tuple(x) for x in lis).values() if y > 1)
2
>>> lis = [[12, 34, 56], [45, 78, 334], [56, 90, 78], [12, 34, 56], [56, 90, 78], [12, 34, 56]]
>>> sum(y for y in Counter(tuple(x) for x in lis).values() if y > 1)
5
In Steps
Convert your sub-list into tuples:
tuple(x) for x in lis
Count them:
>>> Counter(tuple(x) for x in lis)
Counter({(12, 34, 56): 3, (45, 78, 334): 1, (56, 90, 78): 2})
take only the values:
>>> Counter(tuple(x) for x in lis).values()
dict_values([3, 1, 2])
Finally, sum only the ones that have a count greater than 1:
> sum(y for y in Counter(tuple(x) for x in lis).values() if y > 1)
5
Make it Re-usable
Put it into a function, add a docstring, and a doc test:
"""Count duplicates of sub-lists.
"""
from collections import Counter
def count_duplicates(lis):
"""Count duplicates of sub-lists.
Assumption: Sub-list contain only hashable elements.
Result: If a sub-list appreas twice the result is 2.
If a sub-list aprears three time and a other twice the result is 5.
>>> count_duplicates([[12, 34, 56], [45, 78, 334], [56, 90, 78],
... [12, 34, 56]])
2
>>> count_duplicates([[12, 34, 56], [45, 78, 334], [56, 90, 78],
... [12, 34, 56], [56, 90, 78], [12, 34, 56]])
...
5
"""
# Make it a bit more verbose than necessary for readability and
# educational purposes.
tuples = (tuple(elem) for elem in lis)
counts = Counter(tuples).values()
return sum(elem for elem in counts if elem > 1)
if __name__ == '__main__':
import doctest
doctest.testmod(verbose=True)
Run the test:
python count_dupes.py
Trying:
count_duplicates([[12, 34, 56], [45, 78, 334], [56, 90, 78],
[12, 34, 56]])
Expecting:
2
ok
Trying:
count_duplicates([[12, 34, 56], [45, 78, 334], [56, 90, 78],
[12, 34, 56], [56, 90, 78], [12, 34, 56]])
Expecting:
5
ok
1 items had no tests:
__main__
1 items passed all tests:
2 tests in __main__.count_duplicates
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

Why does my program output the wrong highest number?

When I run this program, it says that the max number is 1 digit lower than it actually is in the list. For example, I run the code below and it tells me the max number is 91 when it is 92 from the list.
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 92]]
for eachRow in range(len(examMarks)):
for eachColumn in range(len(examMarks[eachRow])):
eachExamMark = (examMarks[eachRow][eachColumn])
max = -100
for everyMark in range(eachExamMark):
if everyMark > max:
max = everyMark
print(max)
I don't see the reason for the 3 loops to be honest, have you tried something like this?
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 92]]
highest = 0
for marks in examMarks:
for mark in marks:
highest = max(mark, highest)
print('Highest mark: %d' % highest)
You should try this code!
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 12]]
eachExamMark =[]
for eachRow in range(len(examMarks)):
for eachColumn in range(len(examMarks[eachRow])):
eachExamMark.append(examMarks[eachRow][eachColumn])
max = -100
for everyMark in eachExamMark:
if everyMark > max:
max = everyMark
print(max)
eachExamMark will be set to (92) that is the number 92 as the last step of the first part of your program. If you do a for loop over range(92) it will end at 91.
You should at least do:
print(eachExamMark)
before the max = -100 line.
You probably want to do:
eachExamMark.append(examMarks[eachRow][eachColumn])
after defining eachExamMark = [] at the beginning.
I am not sure if you have to solve things this way, but IMHO you should not be using range() at all, and there is no need to build a flattened list either.
You could e.g. do:
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 92]]
print(max(max(x) for x in examMarks))
As others point out the problem is the last loop is performing a range of a number, not a list as you expect.
An alternative algorithm:
from itertools import chain
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 92]]
print(max(chain.from_iterable(examMarks)))
chain.from_iterable(examMarks) flattens the list to an iterator
max() finds the maximum number on the list
Note: My original answer used sum(examMarks, []) to flatten the list. Thanks #John Coleman for your comment on a faster solution.
Try this one:
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 12]]
eachExamMark =[]
for eachRow in examMarks:
eachExamMark.append(max(eachRow))
print max(eachExamMark)

How to make each element in a list another list in python

I have a list inside a loop for e.g
A=[25,45,34,....87]
in the next iteration A should be
A=[[25,32],[45,13],[34,65],....[87,54]]
in the next iteration A should be
A=[[25,32,44],[45,13,67],[34,65,89],....[87,54,42]]
and so on.How can i do that?is it possible?The code i am working on is
s=0
e=25
for i in range(0,4800):
if not m_list_l:
m_list_l.append(max(gray_sum[s:e]))
m_list_l[i].append(max(gray_sum[s:e]))
s+=25
e+=25
But this give me Error as
m_list_l[i].append(max(gray_sum[s:e]))
AttributeError: 'int' object has no attribute 'append'
The first element you insert should be a list, not an int. Change m_list_l.append(max(gray_sum[s:e])) to m_list_l.append([max(gray_sum[s:e])]) to fix this.
Say there are two lists as
A = [i for i in range(10,100,10)]
A
[10, 20, 30, 40, 50, 60, 70, 80, 90]
B = [i for i in range(20,100,10)]
B
[20, 30, 40, 50, 60, 70, 80, 90, 100]
The combined list would be
L = [[i,j] for i,j in zip(A,B)]
L
[[10, 20],
[20, 30],
[30, 40],
[40, 50],
[50, 60],
[60, 70],
[70, 80],
[80, 90],
[90, 100]]

Python sublist within a main list being skipped when iterating using a for loop [duplicate]

This question already has answers here:
Modifying list while iterating [duplicate]
(7 answers)
Closed 8 years ago.
I have a function that takes two parameters (a list and an input number). I have code that breaks the input list into a smaller grouping of lists. I then need to check this new list and make sure all of the smaller lists are at least as long as the input number. However when I try to iterate over the sublists within my main list, for some reason certain sublists are excluded (in my example it is the sublist located at mainlist[1]. Any idea why this is happening???
def some_function(list, input_number)
...
### Here I have other code that further breaks down a given list into groupings of sublists
### After all of this code is finished, it gives me my main_list
...
print main_list
> [[12, 13], [14, 15, 16, 17, 18, 19], [25, 26, 27, 28, 29, 30, 31], [39, 40, 41, 42, 43, 44, 45]]
print "Main List 0: %s" % main_list[0]
> [12, 13]
print "Main List 1: %s" % main_list[1]
> [14, 15, 16, 17, 18, 19]
print "Main List 2: %s" % main_list[2]
> [25, 26, 27, 28, 29, 30, 31]
print "Main List 3: %s" % main_list[3]
> [39, 40, 41, 42, 43, 44, 45]
for sublist in main_list:
print "sublist: %s, Length sublist: %s, input number: %s" % (sublist, len(sublist), input_number)
print "index of sublist: %s" % main_list.index(sublist)
print "The length of the sublist is less than the input number: %s" % (len(sublist) < input_number)
if len(sublist) < input_number:
main_list.remove(sublist)
print "Final List >>>>"
print main_list
> sublist: [12, 13], Length sublist: 2, input number: 7
> index of sublist: 0
> The length of the sublist is less than the input number: True
> sublist: [25, 26, 27, 28, 29, 30, 31], Length sublist: 7, input number: 7
> index of sublist: 1
> The length of the sublist is less than the input number: False
> sublist: [39, 40, 41, 42, 43, 44, 45], Length sublist: 7, input number: 7
> index of sublist: 2
> The length of the sublist is less than the input number: False
> Final List >>>>
> [[14, 15, 16, 17, 18, 19], [25, 26, 27, 28, 29, 30, 31], [39, 40, 41, 42, 43, 44, 45]]
Why is my sublist located at mainlist[1] being completely skipped??? Thanks for any help in advance.
An 'if' in a list comprehension would work:
>>> x = [[12, 13], [14, 15, 16, 17, 18, 19], [25, 26, 27, 28, 29, 30, 31], [39, 40, 41, 42, 43, 44, 45]]
>>> [y for y in x if len(y)>=7]
[[25, 26, 27, 28, 29, 30, 31], [39, 40, 41, 42, 43, 44, 45]]
It looks like you're changing the list as you iterate over it. This is not allowed and can lead to undefined behavior.
See this answer.

Categories