select qualified element from 2D array into a new list - python

I have a 2D array of integer value:
[[26, 9, 24, 13],
[16, 14, 39, 29]]
I need to select the number >= 14, ends in 9 or 4, and not 39. It returns 1 if the criteria meets, otherwise return 0, i.e.
[[0, 0, 1,0],
[0,0,0,1]]
updated: code suggested by Tomothy32
result = result = [[int(x >= 14 and x % 10 in (4, 9) and x != 19) for x in sl] for sl in X]
another nested loop approach
def test(X):
out = [[0]*len(X[0]) for _ in range(len(X))]
for i in range(len(X)):
for j in range(len(X[i])):
check = X[i][j]
if check>=14 and check%5==4 and check!=39:
out[i][j] = 2
return out

You can use a list comprehension:
x = [[26, 9, 43, 13],
[16, 14, 39, 29]]
result = [[int(x >= 14 and x % 10 == 9 and x != 39) for x in sl] for sl in x]
print(result)
# [[0, 0, 0, 0], [0, 0, 0, 1]]
To get the last digit, use the remainder/modulo operator.

Change this statements:
if element >=14 and element !=39:
to
if element >=14 and element !=39 and element%10==9:

Related

Loop of List into a Tabbed New List

I am a high school student. By observing the inputted sequence, I want to create a program that creates general formulas on quadratic to a polynomial with nth power equations. This posted code will function as a means of validation for inputted sequences. If you have a better code, please help me. Thank You!
The same concept was shown below,
here is my code
def shrink(numbers):
n1 = [(x, numbers[i+1]) for i, x in enumerate(numbers)
if i < len(numbers)-1]
n2 = [x[1]-x[0] for x in n1]
print(n2)
if(len(n2) > 1):
return shrink(n2)
return n
#shrink([1, 8, 27, 64, 125, 216])
a = input()
b = a.split()
for i in range(len(b)):
b[i] = int(b[i])
shrink(b)
"""
The output will be:
[7, 19, 37, 61, 91]
[12, 18, 24, 30]
[6, 6, 6]
[0, 0]
[0]
"""
#I want the output from the top to be like this!
d = [
[7, 19, 37, 61, 91],
[12, 18, 24, 30],
[6, 6, 6],
[0, 0],
[0]
]
if d[2][0] == d[2][1]:
print('cubic sequence')
During the first call you initialize a list variable which you update and pass to the recursive call
def shrink(numbers,return_list = []):
n1 = [(x, numbers[i+1]) for i, x in enumerate(numbers) if i < len(numbers)-1]
n2 = [x[1]-x[0] for x in n1]
return_list.append(n2)
if(len(n2) > 1):
return shrink(n2,return_list)
else:
return return_list
print(shrink([1, 8, 27, 64, 125, 216]))
If you want the values of n1 as well :
def shrink(numbers,n1_list = [], n2_list = []):
n1 = [(x, numbers[i+1]) for i, x in enumerate(numbers) if i < len(numbers)-1]
n2 = [x[1]-x[0] for x in n1]
n1_list.append(n1)
n2_list.append(n2)
# print(n2)
if(len(n2) > 1):
return shrink(n2,n1_list,n2_list)
else:
return n1_list,n2_list
print(shrink([1, 8, 27, 64, 125, 216]))
Thank You Atharva Gundawar.
If you want the list to be inputted, this is the answer:
Take note that input list should be separated by space and not by a comma.
Sample input: 1 8 27 64 125 216
def shrink(numbers, return_list=[]):
n1 = [(x, numbers[i + 1]) for i, x in enumerate(numbers) if i < len(numbers) - 1]
n2 = [x[1] - x[0] for x in n1]
return_list.append(n2)
if (len(n2) > 1):
return shrink(n2, return_list)
else:
return return_list
a = input()
b = a.split()
for i in range(len(b)):
b[i] = int(b[i])
c = shrink(b)
print(shrink(b))
print(c[2][0])
print(c[2][1])
if c[2][0] == c[2][1]:
print('cubic sequence')
Input:
1 8 27 64 125 216
Output:
[[7, 19, 37, 61, 91], [12, 18, 24, 30], [6, 6, 6], [0, 0], [0], [7, 19, 37, 61, 91], [12, 18, 24, 30], [6, 6, 6], [0, 0], [0]]
6
6
cubic sequence
This is the correct answer to eradicate the loop:
https://stackoverflow.com/posts/70423499/revisions
def shrink(numbers, return_list=[]):
n1 = [(x, numbers[i + 1]) for i, x in enumerate(numbers) if i < len(numbers) - 1]
n2 = [x[1] - x[0] for x in n1]
return_list.append(n2)
if (len(n2) > 1):
return shrink(n2, return_list)
else:
return return_list
input_user = input("Enter data:")
b = input_user.split()
for num in range(len(b)):
b[num] = int(b[num])
c = shrink(b)
print(c)

Moving specific number (without sort) to the left of list

I want to just move the zero's to left and don't want to sort the list.
For example, if my list is like:
nums = [1, 10, 20, 0, 59, 63, 0, 8, 0]
Here's the output which I desire after moving all the Zero's to left:
output = [0, 0, 0, 1, 10, 20, 59, 63, 8]
Here's the code I tried:
class Solution:
def moveZeroes(self, nums):
c = 0
for i in range(len(nums)):
if nums[i] != 0:
nums[i], nums[c] = nums[c], nums[i]
c += 1
return nums
print(Solution().moveZeroes(nums))
This code gives me output as:
[1, 10, 20, 59, 63, 8, 0, 0, 0]
But my desired output is:
[0, 0, 0, 1, 10, 20, 59, 63, 8]
You can use sorted() with key as bool to achieve this as:
>>> nums = [1, 10, 20, 0, 59, 63, 0, 8, 0]
>>> sorted(nums, key=bool)
[0, 0, 0, 1, 10, 20, 59, 63, 8]
It will work for 0s. In order to make it more generic for any number, you can define key as lambda x: x!=left_num:
>>> left_num = 0
>>> sorted(nums, key=lambda x: x!=left_num)
[0, 0, 0, 1, 10, 20, 59, 63, 8]
As an alternative, here's a less Pythonic (but efficient) version of it using list.count():
>>> nums = [1, 10, 20, 0, 59, 63, 0, 8, 0]
>>> left_num = 0
>>> [left_num]*nums.count(left_num) + [n for n in nums if n!=left_num]
[0, 0, 0, 1, 10, 20, 59, 63, 8]
Here I am finding the count of zeroes in the list (say n), and assigning n zeroes in the start of new list. To get the rest of the unsorted list, I am using list comprehension to filter out the 0s from the list.
output = []
for i in nums:
if i == 0:
output.insert(0, 0)
else:
output.append(i)
output
sorted(nums, key=lambda i: i != 0)
# or
sorted(nums, key=bool)
you could filter out the zeros and insert the number of removed zeros at the begining of the output list:
nums = [1, 10, 20, 0, 59, 63, 0, 8, 0]
output = list(filter(None,nums))
output = [0]*(len(nums)-len(output)) + output
print(output)
# [0, 0, 0, 1, 10, 20, 59, 63, 8]
since the question does not mention any constraints, maybe this fine piece of one-line will help you:
def zero_left(list):
return [x for x in list if x == 0] + [x for x in list if x!=0]

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]]

Python Numpy Array geht values of neighbours

I want to get all neighbour values of a np.array.
The array looks like:
x = np.array([ [1, 2, 3, 4 ],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16] ])
What I have is:
i = 2
j = 2
n = x[i,j-1], x[i,j], x[i,j+1], x[i-1,j], x[i+1,j], x[i-1,j-1], x[i+1,j+1], x[i+1,j-1], x[i-1,j+1]
This returns (what I want)
(10, 11, 12, 7, 15, 6, 16, 14, 8)
But also got bugs for example when i want the neightbour values of
i = 3
j = 3
That gives:
Exception has occurred: IndexError
index 4 is out of bounds for axis 1 with size 4
An other soultion is:
def find_neighbors(m, i, j, dist=1):
return [row[max(0, j-dist):j+dist+1] for row in m[max(0,-1):i+dist+1]]
and
n = find_neighbors(x, i, j)
Which gives me an array of the neightbours but also gives me not all neightbours when I set
i = 0
j = 0
because it only gives me:
[array([1, 2]), array([5, 6])]
Does anybody have a solution for this?
Thank you!
You can take advantage of python indexing wrapping around for negative indices.
def wrap_nb(x,i,j):
return x[np.ix_(*((z-1, z, z+1-S) for z,S in zip((i,j), x.shape)))].ravel()
This requires i and j to be nonnegative and less than the shape of x.
If that is not guaranteed:
def wrap_nb(x,i,j):
return x[np.ix_(*(np.r_[z-1:z+2]%S for z,S in zip((i,j), x.shape)))].ravel()
Examples:
>>> wrap_nb(x,1,-2)
array([ 2, 3, 4, 6, 7, 8, 10, 11, 12])
>>> wrap_nb(x,0,-1)
array([15, 16, 13, 3, 4, 1, 7, 8, 5])
>>> wrap_nb(x,0,0)
array([16, 13, 14, 4, 1, 2, 8, 5, 6])
# function to find the start row and column
def find_start(x):
start = x-1 if x-1 >= 0 else 0
return start
# function to find the end row and column
def find_end(x, shape):
end = x+1 if x+1 <= shape else shape
return end
def find_neighbors(a, i, j):
neighbors = []
row_start, row_end = find_start(i), find_end(i, a.shape[0])
col_start, col_end = find_start(j), find_end(j, a.shape[1])
for y in range(a.shape[0]):
for z in range(a.shape[1]):
if y >= row_start and y <= row_end:
if z >= col_start and z <= col_end:
neighbors.append(a[y][z])
return neighbors
i, j = 0, 0
neighbors = find_neighbors(a, i, j)
print(neighbors)
Output: [1, 2, 5, 6]
i, j = 3, 3
neighbors = find_neighbors(a, i, j)
neighbors
Output: [11, 12, 15, 16]
i, j = 2, 2
neighbors = find_neighbors(a, i, j)
neighbors
Output: [6, 7, 8, 10, 11, 12, 14, 15, 16]
This would cover all the edge cases.
I got the following solution form an mate:
New array:
homes = np.array([ [1, 2, 3, 4 ],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16] ])
Code for returning the neighbour values:
neighbour = []
neighbour += [homes[i][j]] # value itself
neighbour += [homes[i][(j + 1) % n]] # value right
neighbour += [homes[i][(j - 1) % n]] # value left
neighbour += [homes[(i + 1) % n][j]] # value down
neighbour += [homes[(i + 1) % n][(j + 1) % n]] # value right down
neighbour += [homes[(i + 1) % n][(j - 1) % n]] # value left down
neighbour += [homes[(i - 1) % n][j]] # vlaue up
neighbour += [homes[(i - 1) % n][(j + 1) % n]] # vlaue right up
neighbour += [homes[(i - 1) % n][(j - 1) % n]] # value left up
Which returns me:
i = 0
j = 0
[16, 13, 15, 4, 1, 3, 12, 9, 11]
Thats what I need but I'am still interessed in solution like the one from Abdur

element wise checking of nested list

Check nested list elementwise for multiple conditions and return 0 or 1 if condition is not met or is met.
I have to check
at least 14
cannot be equal to= 19
if the element ends in 4 or 9
For example, age array of
[[22, 13, 31, 13],
[17, 14, 24, 22]]
will have the output array as
[[0, 0, 0, 0],
[0, 1, 1, 0]]
I've tried flattening the list and then checking each condition, but it's not working.
flat_list = [item for sublist in age for item in sublist]
x=14
[not x for x in flat_list]
There's a faster numpy solution:
((arr >= 14) & (arr != 19) & ((arr%10 == 4) | (arr%10==9))).astype(int)
Code:
import numpy as np
arr = np.array([[22, 13, 31, 13],
[17, 14, 24, 22]])
print(((arr >= 14) & (arr != 19) & ((arr%10 == 4) | (arr%10==9))).astype(int))
# [[0 0 0 0]
# [0 1 1 0]]
You could do it with list comprehensions like so:
somelist = [[22, 13, 31, 13],
[17, 14, 24, 22]]
result = [[1 if (x%10==4 or x%10==9) and (x>=14 and x!=19) else 0 for x in sublist] for sublist in somelist]
result
[[0, 0, 0, 0], [0, 1, 1, 0]]
Where x%10 will get the last digit in each number, allowing the direct comparison. By grouping the two conditions, you can more logically lay out what you want to do, though this gets a bit messy for a list comprehension.
A better way (at the potential expense of speed) might be to use map:
def check_num(num):
value_check = num >= 14 and num != 19
last_num_check = num % 10 == 4 or num % 10 == 9
return int(value_check and last_num_check)
somelist = [[22, 13, 31, 13],
[17, 14, 24, 22]]
result = [[x for x in map(check_num, sublist)] for sublist in somelist]
result
[[0, 0, 0, 0], [0, 1, 1, 0]]
Timing the difference between operations:
List Comprehension
python -m timeit -s 'somelist = [[22, 13, 31, 13], [17, 14, 24, 22]]' '[[1 if (x%10==4 or x%10==9) and (x>=14 and x!=19) else 0 for x in sublist] for sublist in somelist]'
1000000 loops, best of 3: 1.35 usec per loop
Map
python -m timeit -s 'from somefunc import check_num; somelist = [[22, 13, 31, 13], [17, 14, 24, 22]]' '[[x for x in map(check_num, sublist)] for sublist in somelist]'
100000 loops, best of 3: 3.37 usec per loop
C.Nvis has a good answer with list comprehension. You can also solve this using nested for loops
def is_valid(x):
return (x == 14) or (x%10 == 4) or (x%10 == 9)
out = []
for sublist in matrix:
out_sublist = []
for i in sublist:
if (is_valid(i)):
out_sublist.append(1)
else:
out_sublist.append(0)
out.append(out_sublist)
print(out)
These answers are effectively the same algorithm.
Just for your example it can be done with a bit of mapping.
The way you can verify that the last digit equals to a number is by applying a modulo-10 on the number.
my_list = [[22, 13, 31, 13],[17, 14, 24, 22]]
result_list = []
for sublist in my_list:
result_list.append(list(map(lambda x: 1 if x % 10 == 4 and x >= 14 and x != 19 else 0, sublist)))
print(result_list)
will yield:
[[0, 0, 0, 0], [0, 1, 1, 0]]

Categories