Complex list and len computation - python

The following code has a output of [1, 3, 6, 10]. I understand how to get 1 and 3 but not 6 and 10.
In 1st loop, the first list item 1 is equal to[my_list[0]], 3 equals to [out_list[len(out_list)-1] + my_list[i]]
In 2nd loop, out_list = 4 + [1 + 3] = 8which is not 6...
def mystery(my_list):
out_list = [my_list[0]]
for i in range(1, len(my_list)):
out_list += [out_list[len(out_list)-1] + my_list[i]]
print(out_list)
mystery([1, 2, 3, 4]) #output[1, 3, 6, 10]
I'm very close to understand it, just need a bit more explanation. Am I right? 1st loop, out_list = 1, [out_list[len(out_list)-1] = 1, my_list[i]] = 2, therefore, [1, 3]. 2nd loop, out_list stays the same, then I'm stuck here...

output = mystery([1, 2, 3, 4]) # [1, 3, 6, 10]
output == [1, 1+2, 1+2+3, 1+2+3+4]

my_list initially is : [1, 2, 3, 4]
out_list initially is : [1]
out_list in 1 iteration outlist on each iter : [1]
here i is : 1
len(out_list) : 1 my_list[i]: 2
add next element using this statement : out_list += [out_list[len(out_list)-1] + my_list[i]]
check here : out_list[0] gives 1 add this to 2
out_list in 2 iteration outlist on each iter : [1, 3]
here i is : 2
len(out_list) : 2 my_list[i]: 3
add next element using this statement : out_list += [out_list[len(out_list)-1] + my_list[i]]
check here : out_list[1] gives 3 add this to 3
out_list in 3 iteration outlist on each iter : [1, 3, 6]
here i is : 3
len(out_list) : 3 my_list[i]: 4
add next element using this statement : out_list += [out_list[len(out_list)-1] + my_list[i]]
check here : out_list[2] gives 6 add this to 4
Finally output is : [1, 3, 6, 10]
out_list += [out_list[len(out_list)-1] + my_list[i]] this statement it appends previous element into out_list i.e why out_list += is used instead out_list = so only in 3rd and 4th iteration the result is 6 and 10

out_list[len(out_list)-1] is simply the last item in out_list, same as out_list[-1].
Adding items to the list is done obscurely. Doing lst += [smtn] is the same as doing lst.append(smtn)
Would this make the function more readable to you?
def mystery(my_list):
out_list = [my_list[0]]
for i in range(1, len(my_list)):
out_list.append(out_list[-1] + my_list[i])
print(out_list)
This code returns a list whose i's item is the sum of the first i items of the input. In the i iteration you take the sum of i-1 items (which is stored in i-1), and add the i-th item from the list. 3=1+2, 6=(1+2)+3, 10=(1+2+3)+4. Had the next item in my_list be 5, the next item in out_list would be 10+5 = 15.
Edit:
To clarify more, let's do it by stages.
my_list = [1,2,3,4] and we enter the method
upon entry, we have out_list = [my_list[0]]. so now out_list = [1].
Now we go into the loop:
First iteration, i=1. out_list[len(out_list)-1] + my_list[i] = out_list[0] + my_list[1] = 1 + 2 = 3. out_list = [1,3]
Second iteration, i=2. out_list[len(out_list)-1] + my_list[i] = out_list[1] + my_list[2] = 3 + 3 = 6. out_list = [1,3,6]
Third iteration, i=3. out_list[len(out_list)-1] + my_list[i] = out_list[2] + my_list[3] = 6 + 4 = 10. out_list = [1,3,6,10]

A pythonic way to do this really easily:
def summer_foo(my_list):
return [sum(my_list[:i+1]) for i in range(len(my_list))]
Brief explanation
Loop from 0 to the len of the list - len(my_list)
Sum all the elements which goes from 0 to i
Put this element in the list (this is done with the comprehension)
if iis equal to 0 you will get the first element.
if iis equal to 1 you will get the sum of the first and the second element (i belongs to [0,2))
And so on...

Related

How to loop over a list and roll over at the end?

I have a list and I must move elements from it to another list, for example, I have this:
lst_one = [1, 2, 3, 4]
iterable = 6
lst_two = []
The result needed is this:
lst_one = []
lst_two = [2, 1, 4, 3]
In this case, the iterable is the steps I move through the list to find the next available number. When I find it, I have to add it to the new list and remove it from the old one. So, if 1 is the first number, I have to run though all the list and if the list is too short, continue counting again from the beginning over and over again, until the number is found and this should continue until there are no elements left in lst_one.
No functions or classes allowed!
I literally cannot start, because the "loop" stops at the end of the list and doesn't continue again from the beginning
lst = input()
num = int(input())
lst = lst.split(" ")
lst = [eval(i) for i in soldiers_list]
new_list = []
for i in range(num - 1, len(lst), num):
new_list.append(lst[i])
del lst[i]
Is this what you need?
lst_one = [1, 2, 3, 4]
iterable = 6
lst_two = []
i = 0
while len(lst_one) != 0:
i = (i+iterable-1) % len(lst_one)
lst_two.append(lst_one[i])
del lst_one[i]
This was an interesting question, OP!
Let's see the process in detail:
First we keep in mind that we need to deal with all the elements present in lst_one.
We can do that by storing the length of lst_one before doing anything else, and setting up a for loop with it:
lst_one = [1, 2, 3, 4]
iterable = 6
lst_one_len = len(lst_one)
for counter in range(lst_one_len):
Let's run through getting the output fpr two elements:
First element, iteration 1: 1, index 0
First element, iteration 2: 2, index 1
First element, iteration 3: 3, index 2
First element, iteration 4: 4, index 3
First element, iteration 5: 1, index 0 (roll over)
First element, iteration 6: 2, index 1
So, we're left with 2. Now, upon deleting 2 from the list, we're left with [1, 3, 4], and we were at index 1, so we continue from there.
Second element, iteration 1: 3, index 1
Second element, iteration 2: 4, index 2
Second element, iteration 3: 1, index 0 (roll over)
Second element, iteration 4: 3, index 1
Second element, iteration 5: 4, index 2
Second element, iteration 6: 1, index 0 (roll over)
So, we're left with 1. Now, upon deleting 1 from the list, we're left with [3, 4], and we were at index 0, so we continue from there.
And so on...
So, we need to keep track of the index we're at.
We can do that by setting up a variable previous_index and setting it to 0 before the for loop:
lst_one = [1, 2, 3, 4]
iterable = 6
lst_one_len = len(lst_one)
previous_index = 0
for counter in range(lst_one_len):
Now, imagine that the index in the previous step (just index, not previous_index), kept growing on beyond 4. This would obviously produce an IndexError, so we need to make sure that it doesn't.
But this also means that we can grow the index beyond 4 and then "collapse" it to the length of our list later.
So, we'll define it as an element index that goes previous_index elements beyond iterable, but we'all also have to subtract 1 to account for the fact that your question assumes indexing starts at 1, not 0:
lst_one = [1, 2, 3, 4]
iterable = 6
lst_two = []
lst_one_len = len(lst_one)
previous_index = 0
for counter in range(lst_one_len):
index = iterable + previous_index - 1
Now, we need to make sure that index doesn't go beyond the length of the list, and that's a simple matter of using the modulo operator %:
lst_one = [1, 2, 3, 4]
iterable = 6
lst_two = []
lst_one_len = len(lst_one)
previous_index = 0
for counter in range(lst_one_len):
index = iterable + previous_index - 1
collapsed_index = index % len(lst_one)
Now, we need to add the element at collapsed_index to lst_two and remove it from lst_one:
lst_one = [1, 2, 3, 4]
iterable = 6
lst_two = []
lst_one_len = len(lst_one)
previous_index = 0
for counter in range(lst_one_len):
index = iterable + previous_index - 1
collapsed_index = index % len(lst_one)
lst_two.append(lst_one[collapsed_index])
del lst_one[collapsed_index]
And finally, we need to set previous_index to collapsed_index so that we can continue from there. Also print the lists to see the result:
lst_one = [1, 2, 3, 4]
iterable = 6
lst_two = []
lst_one_len = len(lst_one)
previous_index = 0
for counter in range(lst_one_len):
index = iterable + previous_index - 1
collapsed_index = index % len(lst_one)
lst_two.append(lst_one[collapsed_index])
del lst_one[collapsed_index]
previous_index = collapsed_index
print(lst_two)

Can anyone help me understand how this for loop is running?

I am pretty familiar with the enumerate and 'range(len(iterable)' way of looping through a for loop. However, for whatever reason I can't seem to understand why the for loop is producing the following output.
lst = [-2, 0, 4, 5, 1, 2]
for num, b in enumerate(lst):
print(lst[b])
Output :
1
-2
1
2
0
4
I understand if I were to print(lst[num]) it would print the items of the list.
If I were to print(i) I would also print the items of the list.
If I print(num) I would print the indices.
I just can't figure out where the output is getting the numbers from.
For the enumerate function, b refers to the elements. But since the elements are also valid indices for the loop, they return a value.
SO:
lst = [-2, 0, 4, 5, 1, 2]
for num, b in enumerate(lst):
print(lst[b])
In this Every iteration is:
1) b = -2 => print(lst[b]) => lst[-2] => 1
2) b = 0 => print(lst[b]) => lst[0] => -2
3) b = 4 => print(lst[b]) => lst[4] => 1
4) b = 5 => print(lst[b]) => lst[5] => 2
5) b = 1 => print(lst[b]) => lst[1] => 0
6) b = 2 => print(lst[b]) => lst[2] => 4
Hence this is valid
lst = [-2, 0, 4, 5, 1, 2]
for index, value in enumerate(lst):
print(value)
# Prints each value
for index, value in enumerate(lst):
print(index)
# Prints each index
for index, value in enumerate(lst):
print(lst[index])
# Prints each value (but not really benefiting from enumerate)
for index, value in enumerate(lst):
print(lst[value])
# Meaningless
# Only works since value itself is an int
# Prints some element in lst whose index equals to value
If you're confused about why a piece of code is doing what it doing, it's frequently helpful to have it print out exactly what it's doing. In this case, printing out the values of b:
>>> lst = [-2, 0, 4, 5, 1, 2]
>>> for b in lst:
... print(f"lst[{b}] = {lst[b]}")
...
lst[-2] = 1
lst[0] = -2
lst[4] = 1
lst[5] = 2
lst[1] = 0
lst[2] = 4
As you can see, the b values go through the lst elements in order, and the lst[b] values that get printed on the right (which are the only values you printed originally) do indeed correspond to what you get by indexing lst.
Note that lists are zero-indexed, so lst[0] is the first element (-2), and a negative index counts that many spaces from the end, so lst[-2] is the second element from the end (1, the same as lst[4]).

How to return the turn of an element in a list?

I want to know if an element is in the list multiple times and if so what is the order of the 2nd one. The 2nd one is important, not the 3rd or the 4th one.
list = [1, 3, 4, 2, 0, 1, 6, 7, 0]
My expected output is:
"1" is in list 2 times and the order of the 2nd "1" is six.
Doing it with one pass over the list, while saving the indexes of the target number and checking their amount in the end:
l = [1, 3, 4, 2, 0, 1, 6, 7, 0]
target = 1
idxs = []
for i, num in enumerate(l):
if num == target:
idxs.append(i)
if len(idxs) > 1:
print(f'"{target}" is in the list {len(idxs)} times and the order of the 2nd "{target}" is {idxs[1]+1}')
else:
print(f'{target} is in the list 0 or 1 times')
The indexes can also be obtained with a neat list-comprehension:
idxs = [i for i, num in enumerate(l) if num == target]
Pretty rough code, just to convey the logic you can apply to get it done:
list = [1, 3, 4, 2, 0, 1, 6, 1, 7, 0]
flagged = []
for index, elem in enumerate(list):
elem_count = list[index:].count(elem)
if elem_count > 1 and elem not in flagged:
flagged.append(elem)
temp_index = list[index + 1:].index(elem)
actual_index = index + temp_index + 1
print(str(elem) + ' is in the list ' + str(elem_count) + ' times and the order of 2nd is ' + str(actual_index))
# OP
# 1 is in the list 3 times and the order of 2nd is 5
# 0 is in the list 2 times and the order of 2nd is 9
Are you sure it's 6 and not 5? Indexing starts from 0.
In any case, you can use index for finding it:
first_idx = list.index(element)
print(list.index(element, first_idx + 1))
Like that you will find the first occurrence of the element and than return the index of the second one. If you want it 6 and not 5 - increment it by 1.

creating sum of odd indexes python

I'm trying to create a function equal to the sum of every other digit in a list. For example, if the list is [0,1,2,3,4,5], the function should equal 5+3+1. How could I do this? My knowledge of Python does not extend much farther than while and for loops. Thanks.
Here is a simple one-liner:
In [37]: L
Out[37]: [0, 1, 2, 3, 4, 5]
In [38]: sum(L[1::2])
Out[38]: 9
In the above code, L[1::2] says "get ever second element in L, starting at index 1"
Here is a way to do all the heavy lifting yourself:
L = [0, 1, 2, 3, 4, 5]
total = 0
for i in range(len(L)):
if i%2: # if this is an odd index
total += L[i]
Here's another way, using enumerate:
L = [0, 1, 2, 3, 4, 5]
total = 0
for i,num in enumerate(L):
if i%2:
total += num
>>> arr = [0,1,2,3,4,5]
>>> sum([x for idx, x in enumerate(arr) if idx%2 != 0])
9
This is just a list comprehension that only includes elements in arr that have an odd index.
To illustrate in a traditional for loop:
>>> my_sum = 0
>>> for idx, x in enumerate(arr):
... if idx % 2 != 0:
... my_sum += x
... print("%d was odd, so %d was added. Current sum is %d" % (idx, x, my_sum))
... else:
... print("%d was even, so %d was not added. Current sum is %d" % (idx, x, my_sum))
...
0 was even, so 0 was not added. Current sum is 0
1 was odd, so 1 was added. Current sum is 1
2 was even, so 2 was not added. Current sum is 1
3 was odd, so 3 was added. Current sum is 4
4 was even, so 4 was not added. Current sum is 4
5 was odd, so 5 was added. Current sum is 9
let's take this list as an example:
l = [1,2,3,4,5]
for even indexes sum:
even_index_eles = l[1::2] # [2, 4]
sum(even_index_eles) # 6
for odd indexes sum:
odd_index_eles = l[::2] # [1, 3, 5]
sum(odd_index_eles) # 9
it's worked with odd or even length of list

Compare 2 lists and print the element of the 2nd list if it is present in first list, but not by using 2 for loops

I have to compare 2 lists, if element of list a is present in list b, then the element of list b is to print.
a = [1, 3, 2, 1, 3]
b = [2, 2, 1, 1, 1, 4, 2, 3]
ans = [1, 1, 1, 3, 2, 2, 2, 1, 1, 1, 3]
I may get the answer by using 2 for loops like:
for a_ in a:
for b_ in b:
if a_ == b_:
print b_
op: 1 1 1 3 2 2 2 1 1 1 3
But I don't want to use 2 for loops. How can I do that with a single loop?
Use collections.Counter to count for you:
from collections import Counter
c = Counter(b)
ans = []
for x in a:
ans += [x]*c.get(x,0)
This is one potential way (a bit messy), just posting it since it turns out Fabricator didn't end up with the correct result.
[item for sublist in ([i] * b.count(i) for i in a) for item in sublist]
Basically, the ([i] * b.count(i) for i in a) part builds the list, but it ends up as a list of lists, so then I did the [item for sublist in list for item in sublist] thing to flatten the list.
It's probably a bit similar to the answer by zondo but this keeps it as a list of numbers instead of a string.
print(" ".join(str(x) for x in a for _ in range(b.count(x))))
This, should be work:
for a_ in a:
if b.count(a_) :
ans+=((str(a_)+' ')*b.count(a_)).strip().split(' ')
list.count(x) count the number of occourrences of x in list.
you can print n times a string simply: *'mystring'times
Hope I helped you!

Categories