Python list slicing - python

I'm not able understand what to do here. Can someone help.
I've a few lists:
array = [7,8,2,3,4,10,5,6,7,10,8,9,10,4,5,12,13,14,1,2,15,16,17]
slice = [2, 4, 6, 8, 10, 12, 15, 17, 20, 22]
intervals = [12, 17, 22]
output = []
intermediate = []
slice is a list of indices I need to get from slicing array. interval is a list of indices used to stop the slicing when slice[i] is interval[j] where i and j are looping variables.
I need to form a list of lists from array based on slice and intervals based on the condition that when slice[i] is not interval[j]
intermediate =intermediate + array[slice[i]:slice[i+1]+1]
here in my case:
when slice[i] and interval[j] are equal for value 12. So I need to form a list of lists from array
intermediate = array[slice[0]:slice[0+1]+1] + array[slice[2]:slice[2+1]+1] + array[slice[4]:slice[4+1]+1]
which is
intermediate = array[2:(4+1)] + array[6:(8+1)] + array[10:(12+1)]
and when slice[i] is interval[j] output = output + intermediate and the slicing is continued.
output = output + [intermediate]
which is
output = output + [array[2:(4+1)] + array[6:(8+1)] + array[10:(12+1)]]
now the next value in interval is 17 so till we have 17 in slice we form another list from array[slice[6]:slice[6+1]+1] and add this to the output. This continues.
The final output should be:
output = [array[slice[0]:slice[0+1]+1] + array[slice[2]:slice[2+1]+1] + array[slice[4]:slice[4+1]+1] , array[slice[6]:slice[6+1]+1], array[slice[8]:slice[8+1]+1]]
which is
output = [[2, 3, 4, 5, 6, 7, 8, 9, 10], [12, 13, 14], [15, 16, 17]]

A straightforward solution:
array_ = [7,8,2,3,4,10,5,6,7,10,8,9,10,4,5,12,13,14,1,2,15,16,17]
slice_ = [2, 4, 6, 8, 10, 12, 15, 17, 20, 22]
intervals = [12, 17, 22]
output = []
intermediate = []
for i in range(0, len(slice_), 2):
intermediate.extend(array_[slice_[i]:slice_[i+1]+1])
if slice_[i+1] in intervals:
output.append(intermediate)
intermediate = []
print output
# [[2, 3, 4, 5, 6, 7, 8, 9, 10], [12, 13, 14], [15, 16, 17]]
I have changed some variable names to avoid conflicts.
On large data, you may convert intervals to a set.

Here is a recursive solution which goes through the index once and dynamically check if the index is within the intervals and append the sliced results to a list accordingly:
def slicing(array, index, stops, sliced):
# if the length of index is smaller than two, stop
if len(index) < 2:
return
# if the first element of the index in the intervals, create a new list in the result
# accordingly and move one index forward
elif index[0] in stops:
if len(index) >= 3:
sliced += [[]]
slicing(array, index[1:], stops, sliced)
# if the second element of the index is in the intervals, append the slice to the last
# element of the list, create a new sublist and move two indexes forward accordingly
elif index[1] in stops:
sliced[-1] += array[index[0]:(index[1]+1)]
if len(index) >= 4:
sliced += [[]]
slicing(array, index[2:], stops, sliced)
# append the new slice to the last element of the result list and move two index
# forward if none of the above conditions satisfied:
else:
sliced[-1] += array[index[0]:(index[1]+1)]
slicing(array, index[2:], stops, sliced)
sliced = [[]]
slicing(array, slice_, intervals, sliced)
sliced
# [[2, 3, 4, 5, 6, 7, 8, 9, 10], [12, 13, 14], [15, 16, 17]]
Data:
array = [7,8,2,3,4,10,5,6,7,10,8,9,10,4,5,12,13,14,1,2,15,16,17]
slice_ = [2, 4, 6, 8, 10, 12, 15, 17, 20, 22]
intervals = [12, 17, 22]

Related

How can I find the longest sub-array that is an arithmetic progression?

If I have a list like this [2, 33, 54, 3, 7, 11, 15, 13, 11, 9, 7, 5, 10, 15, 20, 25]
How can I find the longest arithmetic progression?
The output should be: [15, 13, 11, 9, 7, 5].
Here's my code but it does not work and of course there are a lot of bugs.
Can anyone help?
def find_arithmetic(lst):
temp = 0
cnt = 0
max = 0
for i in range(0,len(lst)-1):
if lst[i+1] - lst[i] == lst[i+2] - lst[i+1]:
temp = i
cnt += 1
if max < cnt:
max = cnt
return str(lst(i,max+1))
print(find_arithmetic([12, 33, 54, 3, 7, 11, 15, 13, 11, 9, 7, 5, 10, 15, 20, 25]))
The defining property of an arithmetic progression is that consecutive elements have the same difference between them. So to find the longest sub-sequence that fits an arithmetic progression, you need to keep track of the difference between consecutive elements, and check that it is the same as the difference between the previous pair.
When this condition is satisfied, you bump up the end-index. If not, you say the current and previous element are the start of a new progression. Finally, you iterate over all the sequences you found and return the longest one.
def find_arithmetic_prog(sequence):
progression_limits = [] # Make a list to keep track of the start and end indices of all progressions you find
start = 0 # Assume your progression starts at the first element
end = 1 # Assume your progression ends at the second element
delta = sequence[1] - sequence[0]
for index in range(2, len(sequence)):
new_delta = sequence[index] - sequence[index - 1]
if delta == new_delta: # The delta is the same as before
end = index # So extend the progression
else: # The delta is different, so add the previous progression to our list and start a new one
progression_limits.append((start, end))
# A new progression from the previous index to the current one
start = index - 1
end = index
delta = new_delta
# Now that we've processed the entire list, we go through all the sequences we found
# And return the longest one
start, end = max(progression_limits, key=lambda item: item[1] - item[0])
return sequence[start:end+1]
Running this with your input gives:
>>> find_arithmetic_prog([12, 33, 54, 3, 7, 11, 15, 13, 11, 9, 7, 5, 10, 15, 20, 25
])
[15, 13, 11, 9, 7, 5]

Inserting a value to list according to a threshold value

I have list a = [1,2,3,6,8,12,13,18,33,23] and list b=[] that is empty. I need each value in list a compare with all the values in the list b by taking the difference of the new value from list a with all the contents of the list b. If the difference is grater than to the value of the threshold, it must insert to list b rather than skip to the next value in a, how can do that?
a =[1,2,3,6,8,12,13,18,33,23]
b=[]
b.append(a[0])
for index in range(len(a)):
for i in range(len(b)):
x = a[index] - b[i]
if x > 1:
b.append(a[index])
print("\nOutput list is")
for v in range(len(b)):
print(b[v])
The desired output is:
output = [1,6,8,12,18,33,23]
To further clarify, in first time the list b have the first item from list a. I need to check if the a[0]-b[0]>1, then insert the value of a[0] in b list, and next if a[1] - b[0]>1 then insert the a[1] in b list , and if [[a[2] -b[0] >1] and [a[2]-b[1] > 1]] then insert a[2] in b list and so on
Here is the probable solution to the stated problem though the output is not matching with your desired outcome. But sharing on the basis of how I understood the problem.
a = [1, 2, 3, 6, 8, 12, 13, 18, 33, 23]
b = []
b.append(a[0])
threshold = 1 # Set Threshold value
for index in range(len(a)):
difference = 0
for i in range(len(b)):
difference = abs(a[index] - b[i])
if difference > threshold:
continue # Keep comparing other values in list b
else:
break # No need for further comparison
if difference > threshold:
b.append(a[index])
print("\nOutput list is")
print(b)
Output is:
Output list is
[1, 3, 6, 8, 12, 18, 33]
Also, I notice that after swapping the last two elements (33 <-> 23 ) of the list a as below:
a = [1, 2, 3, 6, 8, 12, 13, 18, 23, 33]
and running the same code. the output was near to your desired output:
Output list is
[1, 3, 6, 8, 12, 18, 23, 33]
This problem is very interesting now as I put myself into more investigation. And I found it a very interesting. Let me explain. First consider the list a as a list of integer numbers starting from 1 to N. For example:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
and set the threshold to 1
threshold = 1 # Set Threshold value
Now, run the programme with threshold = 1 and you will get the output:
Output list is
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
and if you rerun with threshold = 2, you will get the following output:
threshold = 2
Output list is
[1, 4, 7, 10, 13, 16, 19]
Basically, this programme is basically generating a hopping series of integer numbers where hopping is set to the threshold value.
Interesting!!! Isn't it???

how to create a multidimensional array on the fly using python?

I have a loop which generates a value_list each time it runs, at the end of each iteration i want to append all the lists into a one multi dimensional array
I have:
value_list = [1,2,3,4] in 1st iteration
value_list = [5,6,7,8] in 2nd iteration
value list = [9,10,11,12] in 3rd iteration
etc...
At the end of each iteration I want one multi dimensional array like
value_list_copy = [[1,2,3,4]] in the 1st iteration
value_list_copy = [[1,2,3,4],[5,6,7,8]] in the 2nd iteration
value_list_copy = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
etc...
How could I achieve this?
Thanks
You can use a nested comprehension and itertools.count:
from itertools import count, islice
cols = 4
rows = 5
c = count(1)
matrix = [[next(c) for _ in range(cols)] for _ in range(rows)]
# [[1, 2, 3, 4],
# [5, 6, 7, 8],
# [9, 10, 11, 12],
# [13, 14, 15, 16],
# [17, 18, 19, 20]]
The cool kids might also want to zip the count iterator with itself:
list(islice(zip(*[c]*cols), rows))
# [(1, 2, 3, 4),
# (5, 6, 7, 8),
# (9, 10, 11, 12),
# (13, 14, 15, 16),
# (17, 18, 19, 20)]
If you are using Python3.8 then use Walrus assignment(:=).
For Syntax and semantic.
count=0
rows=5
cols=4
[[(count:=count+1) for _ in range(cols)] for _ in range(rows)]
Output:
[[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20]]
Without using :=.
rows=5
cols=4
[list(range(i,i+cols)) for i in range(1,rows*cols,cols)]
Try this:
limit = 10
length_of_elements_in_each_list = 4
[range(i, i+length_of_elements_in_each_list) for i in range(1, limit)]
You can set a limit and length_of_elements_in_each_list according to your need.
Try this below :
value_list_copy = []
for i in range(n): # ----------> Assuming n is the number of times your loop is running
value_list_copy.append(value_list) # ------ Append your value list in value_list_copy in every iteration
Here you will get an array of arrays.
print(value_list_copy)
Here are two other possible solutions:
Double for loop approach
rows, cols, start = 3, 4, 1
value_list_copy = []
for j in range(rows):
value_list = []
for i in range(start, cols + start):
value_list.append((j*cols)+i)
value_list_copy.append(value_list)
print(
f'value_list = {value_list}\n'
f'value_list_copy = {value_list_copy}\n'
)
List comp method
rows, cols, start = 3, 4, 1
value_list_copy_2 = [
[
(j*cols)+i for i in range(start, cols + start)
] for j in range(rows)
]
print(f'value_list_copy_2 = {value_list_copy_2}')
Python Tutor Link to example code

Python array logic

I am trying to create a list of lists with the input of m and n, where m is the number of lists within the main list and n is the number of elements within each given list. The grid should contain the integers from start to start + rows * cols - 1 and be ascending. But, every odd numbered row should be descending instead.
The code I've written is returning the expected results, but my automated tester is saying it's incorrect. Maybe my logic is messed up somewhere?
inputs:
start = 1, m = 3, n = 5
expected:
[[1,2,3,4,5],[10,9,8,7,6],[11,12,13,14,15]]
result = []
mylist = []
start = 1
for x in range(0, rows):
for x in range(0, cols):
result.append(start)
start += 1
for y in range(0, rows):
if y%2 != 0:
mylist.append(result[cols - 1::-1])
del result[cols - 1::-1]
else:
mylist.append(result[0:cols])
del result[0:cols]
return mylist
One possible solution, using itertools.count:
from itertools import count
def build(m, n, start=1):
lst, c = [], count(start)
for i in range(m):
lst.append([next(c) for j in range(n)][::-1] if i % 2 else [next(c) for j in range(n)])
return lst
print(build(3, 5, 1))
Prints:
[[1, 2, 3, 4, 5], [10, 9, 8, 7, 6], [11, 12, 13, 14, 15]]
print(build(3, 0, 1))
Prints:
[[], [], []]
just generate the list of numbers you need which will be n * m, in your case that would generate 0 to 14 in the python range function. However as we want to start at ` then we need to add the start offset too the range end.
Now we can generate all the numbers we need we just need to think about how to create them.
well we can add numbers to the list until the list reaches the size of n, then we need to start a new list, However if the list we just finished is an even numbered row then we need to reverse that list.
def build_lists(m, n, start=1):
data =[[]]
for i in range(start, n * m + start):
if len(data[-1]) < n:
data[-1].append(i)
else:
if len(data) % 2 == 0:
data[-1] = data[-1][::-1]
data.append([i])
if len(data) % 2 == 0:
data[-1] = data[-1][::-1]
return data
print(build_lists(3, 5))
print(build_lists(6, 3))
print(build_lists(6, 2, 100))
OUTPUT
[[1, 2, 3, 4, 5], [10, 9, 8, 7, 6], [11, 12, 13, 14, 15]]
[[1, 2, 3], [6, 5, 4], [7, 8, 9], [12, 11, 10], [13, 14, 15], [18, 17, 16]]
[[100, 101], [103, 102], [104, 105], [107, 106], [108, 109], [111, 110]]

How to loop through a list where data points are dependent on each other?

I have a list, a = [5, 4, 9, 3, 6, 6, 8, 2], and I essentially want to sum the first three numbers, and that sum will be the first value in the new list. The next value in the new list will be the sum of 4, 9, and 3...etc. etc. How to loop this in Python?
list slicing is a good method.
all you need to do is travese from start index to end index-2 , ( can make sum of last 3 element and when you reach second last or last ement you wont be able to take 3 elemnts)
here you can take 3 elemnts and using list slicing, slice list from the
current index to next 3 index ie a[i:i+3] where [i,i+3) is range. then on that new list performing sum operation and appending the reuslt to final list.
a = [5, 4, 9, 3, 6, 6, 8, 2]
res=[]
for i in range(len(a)-2):
res.append(sum(a[i:i+3]))
print(res)
output
[18, 16, 18, 15, 20, 16]
One liner:
list(map(sum, zip(a, a[1:], a[2:])))
Output:
[18, 16, 18, 15, 20, 16]
So you are creating the required sublists of the numbers you want to add up and then you sum each sublist using the high-order function map.
If I understood what you want:
b = [sum(a[i : i+3]) for i in range(0, len(a)-2)]

Categories