How to subtract a number by the next number? - python

What I have right now:
a_list = [25, 23, 12, 8, 4 ,2, 1]
new_list = []
for i, num in enumerate(a_list):
new_num = num - num[i+1]
new_list.append(new_num)
print(new_list)
#Error: new_num = num - num[i+1]
TypeError: 'int' object is not subscriptable
#Expected: [2, 11, 4, 2, 1]

zip is appropriate here, instead of enumerate. Simply zip a_list with a_list[1:] (so that you can "see" two consecutive elements) and find differences.
new_list = [i-j for i, j in zip(a_list, a_list[1:])]
The reason enumerate doesn't work with your implementation is that you want to index an integer in a_list by num[i+1] which is nonsensical.
If you absolutely want to use enumerate, one important thing is to ensure that you don't want get an IndexError, i.e. you don't want to index beyond the list. One way to ensure that doesn't happen is to only enumerate until a_list[:-1]. Then make sure you index a_list (and not num) and you're good to go.
new_list = []
for i, num in enumerate(a_list[:-1]):
new_num = num - a_list[i+1]
new_list.append(new_num)
Output:
[2, 11, 4, 4, 2, 1]

You seem to want:
a_list = [25, 23, 12, 8, 4 ,2, 1]
new_list = [a - b for a, b in zip(a_list, a_list[1:])]
print(new_list)
If you use a library like numpy, this is simpler:
import numpy as np
a_arr = np.array([25, 23, 12, 8, 4 ,2, 1])
new_arr = a_arr[:-1] - a_arr[1:]
print(new_arr)
Both solutions do the same thing using slicing, taking the original list and pairing each element with the same list, minus the first element. zip() automatically omits the last element from the first list, since there is no element to pair it with in the second list. numpy wants you to tell it to omit the last element (a_arr[:-1]) so that they have the same size.

You're trying to use indices with num, which is the value at position i in the list, not the list. Iterate over the list with range(a_list)-1, so that you access the numbers at positions i and i+1 directly from the list.

Okay, it's Pretty Simple...What you can do basically just subtract arr[index] - arr[index + 1] and append it to a new list and after just print it note range should be (0, old_list.len() - 1)
a_list = [25, 23, 12, 8, 4 ,2, 1] #old list
nw_lst = [] #new list to print and where we will append
size = len(a_list); #Size of the old_list
for i in range(0, size-1):
x = a_list[i] - a_list[i + 1] #claculating difference
nw_lst.append(x) #appending the difference to new list
print(nw_lst) #printing new list
OUTPUT:
[2, 11, 4, 4, 2, 1]

Related

create sub-list of order integers present in a list and store them in another nested list in python

I have an array list like this:
list = [1,2,3,4,9,1,12,9,8,7,8,9,10,12,16,1,2,3,4,5,6,7,8,9,10]
I want to create a sub-list from a list of ordered numbers (which are already in sequence in arr_list for e.g. 1,2,3,4 are already in order, similarly 7,8,9,10 and last 10 numbers)
Final output will look like this:
[[1,2,3,4],[7,8,9,10],[1,2,3,4,5,6,7,8,9,10]]
Tried comparing if the i'th element of first for loop is less than the j'th element of second for loop.
This is what i've tried:
sub_list=[]
for i in range(0,length_of_list):
for j in range(i+1,length_of_list):
if (arr_list[i] < arr_list[j]):
sub_list.append(arr_list[i])
else:
pass
New to python, any leads are much appreciated.
Try this...
res, temp = [], []
lst = [1,2,3,4,9,1,12,9,8,7,8,9,10,12,16,1,2,3,4,5,6,7,8,9,10]
for i in lst:
if (not temp) or (temp[-1] == i-1):
temp.append(i)
else:
res.append(temp)
temp = [i]
res.append(temp)
print([i for i in res if len(i)>1])
Outputs:
[[1, 2, 3, 4], [7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
tell me if its okay for you...

Invert the list by exchanging the first and last element, the second and second last, and so on

So Basically the task is to invert the List by changing the first element with the last one, the second one with the second last etc...
This is what i tried, but nothing happend in the end. Do you have any ideas whats not working here or what different approach i should try?
list=[3,6,9,12,15,18,21,24,27,30]
y = 0
x = len(list)-1
while y <= x:
for i in list:
list[y],list[x]=list[x],list[y]
y+=1
x-=1
for i in list:
print(i)
All the other solutions are good approaches, but if you were specifically
asked to write the logic for inverting the list by changing the first element with last element and so on..here,
y = 0
x = len(list)-1
while y < x:
list[y],list[x]=list[x],list[y]
y+=1
x-=1
for i in list:
print(i)
You can do something like this:
def reverse(lst):
# Iterate over the half of the indexes
for i in range(len(lst) // 2):
# Swap the i-th value with the i-th to last value
lst[i], lst[len(lst)-1-i] = lst[len(lst)-1-i], lst[i]
lst = [1, 2, 3, 4, 5]
reverse(lst)
print(lst) # Outputs [5, 4, 3, 2, 1]
lst = [1, 2, 3, 4]
reverse(lst)
print(lst) # Outputs [4, 3, 2, 1]
You can use the reverse() function:
l = [3,6,9,12,15,18,21,24,27,30]
l.reverse()
You can do as follow:
l=[3,6,9,12,15,18,21,24,27,30]
new_l=l[::-1]
The following will invert the order of a list:
>>> l = [3,6,9,12,15,18,21,24,27,30]
>>> l[::-1]
Out[11]: [30, 27, 24, 21, 18, 15, 12, 9, 6, 3]
You can use this code :
for i in sorted(list,reverse=True):
print(i)

Check if content of index equals content of next index

array = [1, 1, 1, 1, 1, 1, 2]
new_array = [x for x in array if array[array.index(x)] != array[array.index(x) + 1]]
print(new_array)
Hi, I'm trying to write a program that will check if a content of an index (example: list[0]) equals to next index and if not append the number that differs and I tried to use a new skill I learned which is list comprehension and I don't quite understand why doesn't it work how it should work
To make it more clear what I mean is if I am given an array with all numbers the same except one number which in this case is two I want to append it in a list I also added a picture to make it even more clear
You can use this simple one liner
print(a[0] if a.count(a[0]) == 1 else min(set(a).difference(a[:1])))
Note: I'm using min() to just to get the element from set.
Output:
>>> a=[1, 1, 2]
>>> print(a[0] if a.count(a[0]) == 1 else min(set(a).difference(a[:1])))
2
>>> a = [17, 17, 3, 17, 17, 17, 17]
>>> print(a[0] if a.count(a[0]) == 1 else min(set(a).difference(a[:1])))
3
IndexError: list index out of range means you are passing an index that isn't present in the list. And that error is raised in this part:
array[array.index(x) + 1]
When x is the last element error is raised. Because there is no index after the last element. In your case, using list comprehension isn't the best choice, you should prefer for loop.
it may help you:
list = [1, 1, 2, 3, 4, 4]
for i, j in enumerate(list[:-1]):
if j == list[i+1]:
#dosomething

Find smallest repeated piece of a list

I've got some list with integers like:
l1 = [8,9,8,9,8,9,8],
l2 = [3,4,2,4,3]
My purpose to slice it into the smallest repeated piece. So:
output_l1 = [8,9]
output_l2 = [3,4,2,4]
Biggest problem that the sequences not fully finished every time. So not
'abcabcabc'
just
'abcabcab'.
def shortest_repeating_sequence(inp):
for i in range(1, len(inp)):
if all(inp[j] == inp[j % i] for j in range(i, len(inp))):
return inp[:i]
# inp doesn't have a repeating pattern if we got this far
return inp[:]
This code is O(n^2). The worst case is one element repeated a lot of times followed by something that breaks the pattern at the end, for example [1, 1, 1, 1, 1, 1, 1, 1, 1, 8].
You start with 1, and then iterate over the entire list checking that each inp[i] is equal to inp[i % 1]. Any number % 1 is equal to 0, so you're checking if each item in the input is equal to the first item in the input. If all items are equal to the first element then the repeating pattern is a list with just the first element so we return inp[:1].
If at some point you hit an element that isn't equal to the first element (all() stops as soon as it finds a False), you try with 2. So now you're checking if each element at an even index is equal to the first element (4 % 2 is 0) and if every odd index is equal to the second item (5 % 2 is 1). If you get all the way through this, the pattern is the first two elements so return inp[:2], otherwise try again with 3 and so on.
You could do range(1, len(inp)+1) and then the for loop will handle the case where inp doesn't contain a repeating pattern, but then you have to needlessly iterate over the entire inp at the end. And you'd still have to have to have return [] at the end to handle inp being the empty list.
I return a copy of the list (inp[:]) instead of the list to have consistent behavior. If I returned the original list with return inp and someone called that function on a list that didn't have a repeating pattern (ie their repeating pattern is the original list) and then did something with the repeating pattern, it would modify their original list as well.
shortest_repeating_sequence([4, 2, 7, 4, 6]) # no pattern
[4, 2, 7, 4, 6]
shortest_repeating_sequence([2, 3, 1, 2, 3]) # pattern doesn't repeat fully
[2, 3, 1]
shortest_repeating_sequence([2, 3, 1, 2]) # pattern doesn't repeat fully
[2, 3, 1]
shortest_repeating_sequence([8, 9, 8, 9, 8, 9, 8])
[8, 9]
shortest_repeating_sequence([1, 1, 1, 1, 1])
[1]
shortest_repeating_sequence([])
[]
The following code is a rework of your solution that addresses some issues:
Your solution as posted doesn't handle your own 'abcabcab' example.
Your solution keeps processing even after it's found a valid result, and then filters through both the valid and non-valid results. Instead, once a valid result is found, we process and return it. Additional valid results, and non-valid results, are simply ignored.
#Boris' issue regarding returning the input if there is no repeating pattern.
CODE
def repeated_piece(target):
target = list(target)
length = len(target)
for final in range(1, length):
result = []
while len(result) < length:
for i in target[:final]:
result.append(i)
if result[:length] == target:
return result[:final]
return target
l1 = [8, 9, 8, 9, 8, 9, 8]
l2 = [3, 4, 2, 4, 3]
l3 = 'abcabcab'
l4 = [1, 2, 3]
print(*repeated_piece(l1), sep='')
print(*repeated_piece(l2), sep='')
print(*repeated_piece(l3), sep='')
print(*repeated_piece(l4), sep='')
OUTPUT
% python3 test.py
89
3424
abc
123
%
You can still use:
print(''.join(map(str, repeated_piece(l1))))
if you're uncomfortable with the simpler Python 3 idiom:
print(*repeated_piece(l1), sep='')
SOLUTION
target = [8,9,8,9,8,9,8]
length = len(target)
result = []
results = [] * length
for j in range(1, length):
result = []
while len(result) < length:
for i in target[:j]:
result.append(i)
results.append(result)
final = []
for i in range(0, len(results)):
if results[i][:length] == target:
final.append(1)
else:
final.append(0)
if 1 in final:
solution = results[final.index(1)][:final.index(1)+1]
else:
solution = target
int(''.join(map(str, solution)))
'result: [8, 9]'.
Simple Solution:
def get_unique_items_list(some_list):
new_list = []
for i in range(len(some_list)):
if not some_list[i] in new_list:
new_list.append(some_list[i])
return new_list
l1 = [8,9,8,9,8,9,8]
l2 = [3,4,2,4,3]
print(get_unique_items_list(l1))
print(get_unique_items_list(l2))
#### Output ####
# [8, 9]
# [3, 4, 2]

Loop from a specific point in a list of lists Python

I would like to append to a new list all elements of an existing list of lists after a specific point
m = [[1,2,3],[4,5,10],[6,2,1]]
specific point = m[0][2]
newlist = [3,4,5,10,6,2,1]
You can directly slice off the remainder of the first target list and then add on all subsequent elements, eg:
m = [[1,2,3],[4,5,10],[6,2,1]]
y, x = 0, 2
new_list = m[y][x:] + [v for el in m[y+1:] for v in el]
# [3, 4, 5, 10, 6, 2, 1]
Here's a couple of functional approaches for efficiently iterating over your data.
If sublists are evenly sized, and you know the index from where to begin extracting elements, use chain + islice:
from itertools import chain, islice
n = 3 # Sublist size.
i,j = 0,2
newlist = list(islice(chain.from_iterable(m), i*n + j, None))
If you don't know the size of your sublists in advance, you can use next to discard the first portion of your data.
V = chain.from_iterable(m)
next(v for v in V if v == m[i][j])
newlist = list(V)
newlist.insert(m[i][j], 0)
This assumes there is no identical value earlier in the sequence.
You can put a conditional in your iteration and only add based on that condition. Once you hit that specific index, make your condition true. Something like this:
m = [[1,2,3],[4,5,10],[6,2,1]]
specific_point = (0,2)
newlist = [3,4,5,10,6,2,1]
output = []
for i in range(len(m)):
for j in range(len(m[i])):
if (i,j) < specific_point:
continue
output.append(m[i][j])
output:
[3, 4, 5, 10, 6, 2, 1]
why not flatten the initial list and go from there
flat_list = [item for sublist in m for item in sublist]
would return [1,2,3,4,5,10,6,2,1] so now you're really on flat_list[2:]
Most of the answers only work for this specific shape of nested list, but it's also possible to create a solution that works with any shape of nested list.
def flatten_from(sequence, path=[]):
start = path.pop(0) if path else 0
for item in sequence[start:]:
if isinstance(item, (list, tuple)):
yield from flatten_from(item, path)
else:
yield item
With the example from the question
>>> list(flatten_from([[1, 2, 3], [4, 5, 10], [6, 2, 1]], [0, 2]))
[3, 4, 5, 10, 6, 2, 1]
It also works with any shape and level of nesting of the input data
m = [[1], [[2], [3, 4, 5, 6, 7]], 8, [9, [10, 11]]]
flatten_from(m, [])) # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
flatten_from(m, [2]) # 8, 9, 10, 11
flatten_from(m, [1, 1, 3]) # 6, 7, 8, 9, 10, 11
This is a bit of a bastard algorithm, though. On one hand, it uses nice functional programming concepts: recursion and yield.
On the other hand it relies on the side effect of mutating the path argument with list.pop, so it's not a pure function.
Below solution will work for your case where your array is restricted to list of list and the size of 'sublist' is consistent throughout i.e "3" in your case
m = [[1,2,3],[4,5,10],[6,2,1]] #input 2D array
a, b = 0, 2 #user input --> specific point a and b
flat_list_m = [item for firstlist in m for item in firstlist] #flat the 2D list
print (flat_list_m[len(m[0])*a+b:]) #print from specific position a and b, considering your sublist length is consistent throughout.
I hope this helps! :)

Categories