verify continuous segments in list [closed] - python

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I want to verify if a condition of sequential segments is appearing in a list or not
An example:
I can have two options, either a list would be like this
[7, 7, 7, 7, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 7, 7, 7 ....]
or
[......, 10, 10, 10, 10, 0, 0, 0, 10, 10, 10, 10, ......]
What I want here
is that I want to go through the list and verify if I find 0's between 10's or 10's between 0's .. I return true
Note:
1- Whatever else inside the list is not important for me
2- The number of 0's or 10's is not fixed, they can change .. however, the most important manner, that if there are 0's there have to be 10's before or after .. or the other way around 0's before and after 10's

What about creating a small function that turns the lists into strings and runs a regex against it, You could tidy this up, or I could if you approve this concept
I'm not a regex, expert I'm sure there is another way to do this without using the AttribeError but this will work, someone can improve this, but it works.
import re
def finder(s):
s = ''.join(str(s))
match = re.search(r'0\,\s10,(\s10,)*\s0', s)
try:
if (match.group(0)):
return True
except AttributeError:
pass
match = re.search(r'10\,\s0,(\s0,)*\s10', s)
try:
if (match.group(0)):
return True
except AttributeError:
return False
l1 = [7, 7, 7, 7, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 7, 7, 7]
l2 = [10, 10, 10, 10, 0, 0, 0, 10, 10, 10, 10]
l3 = [5, 5, 3, 1, 0, 1, 1, 1, 8, 10, 0, 8, 9, 9, 5]
print(finder(l1))
print(finder(l2))
print(finder(l3))
(xenial)vash#localhost:~/python/stack_overflow/sept$ python3.7 check.py
True
True
False

from my understanding you can do something like below.
First find the indexes of 0 ,10s then iterate over them to check if main list is having 0 or 10 in between them. Later check for True/False if some found elements it will return True else False will be returned.
from more_itertools import locate
l = [7, 7, 7, 7, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 7, 7, 7]
# get the indexes of 0's and 10's in given list/array
zeros = list(locate(l, lambda x: x == 0))
tens = list(locate(l, lambda x: x == 10))
# check for each combination and return true/false in each time
find_10s = [(10 in (l[zeros[i]:zeros[i]+1])) for i in range(len(zeros))]
find_0s = [(0 in (l[tens[i]:tens[i]+1])) for i in range(len(tens))]
# this line is to check if anything found in above results
print(any(find_10s) or any(find_0s)) #False

Related

Why aren't these 2 loops giving me the same result and how to reduce time complexity?

I want to solve this problem, but this isn't my issue. I only give this as context.
"You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]).
Find two lines that together with the x-axis form a container, such that the container contains the most water.
Return the maximum amount of water a container can store."
The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
I made a simple nested for loop to solve this problem:
for i in range(0, len(height)):
for j in range(0, len(height)):
maxim = max(min(height[i], height[j]) * abs(j - i),maxim)
But this solution takes too long for a bigger array. So I tried to do this with List Comprehension:
mxm = [min(height[i], height[j] * abs(j - i)) for i in range(0, len(height)) for j in range(0, len(height))]
maxim = max(mxm)
The problem is , I have 2 different outputs: the nested for loop works (it returns 49) but the second one returns 8. (the mxm array has these elements: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 6, 4, 8, 8, 8, 8, 8, 2, 6, 0, 2, 6, 6, 6, 6, 6, 2, 2, 2, 0, 2, 2, 2, 2, 2, 4, 5, 5, 2, 0, 4, 5, 5, 5, 4, 4, 4, 4, 4, 0, 4, 4, 4, 6, 8, 8, 6, 8, 4, 0, 3, 8, 3, 3, 3, 3, 3, 3, 3, 0, 3, 7, 7, 7, 7, 7, 7, 7, 3, 0])
Why are they different? And how can I make my solution faster?
In the first example you're applying the min function to just the height values
min(height[i], height[j])
In the second you include the absolute distance between index positions in that min function as well, it'll always apply to height[j] instead of the actual minimum.
min(height[i], height[j] * abs(j - i))
Also regarding your solution, I believe ive seen this problem before. I think what you're looking for is a sliding window.

How to get the position of same Values in multiple Numpy arrays [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have several numpy arrays with sensordata. I need the position for every array with the same time so i can assign them together.
The arrays look something like this but with alot more values (around 1000 and i have 21 arrays):
x1 = [0, 1, 3, 4, 7, 10]
x2 = [1, 3, 7, 8, 9, 10, 11, 12]
x3 = [0, 1, 3, 7, 9, 10]
xn = [1, 3, 6, 7, 8, 9, 10, 11]
Now i need to know the position of every array IF the value is existing in all of them. In the Example that would be the position in all 21 arrays for the timestamp 1, 3, 7 and 10.
As always iam apprechiating every help!
Here's a rather primitive approach (illustrated for 3 arrays, but easily extendable to an arbitrary number of arrays):
x1 = np.array([0, 1, 3, 4, 7, 10])
x2 = np.array([1, 3, 7, 8, 9, 10, 11, 12])
x3 = np.array([0, 1, 3, 7, 9, 10])
arrays = [x1, x2, x3]
Fetch the values that are in all arrays (pack array values in sets and intersect over all sets):
from functools import reduce
values = reduce(set.intersection, arrays, set(x1))
Result:
{1, 10, 3, 7}
Then select for each of those values the corresponding indices from the arrays and pack them into a dictionary:
indices = {value: tuple(i
for array in arrays
for i in range(len(array))
if array[i] == value)
for value in values}
Result:
{1: (1, 0, 1), 10: (5, 5, 5), 3: (2, 1, 2), 7: (4, 2, 3)}
But: This only works if the values in the arrays are unique!

Slicing lists for getting just quarter of them in the same length

I have a list with lengths of A. Is there a way using slicing to take just every fourth value but maintaining it's length? For example, If this is my list:
A = [0,1,2,3,4,5,6,7,8....]
I want to use slicing to receive:
A = [0,0,0,0,4,4,...]
Using the [::4] is doing the job for the taking every fourth value, but without the other values I want.
If you have:
A = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Then you can do:
>>> [v for v in A[::4] for _ in range(4)]
[0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12]
>>>
I should mention that this rounds the result list length up to a multiple of 4, so you always get 4 of each value included in the result. If you want to drop the extra values at the end, you can append [:len(A)] to the end.
you could do :
A = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
repeatedA = [ A[(i//4) * 4 ] for i in range(len(A))]
the i//4 here allows to get the quotient of the division of the index by 4, then (i//4) * 4 allows us to find the closest multiple of 4 to i smaller than i, so here 1,2,3 are not dividors of 4 but 0 is , which is the closest multiple to them, it's the same with 5,6, and 7, 4 is the closest multiple ( given that it should always be smaller than either of them ), it's equivalent to i - i%4, which allows us to round i down to the closest dividor of 4 given that i = 4* (i//4 ) + 4%i
This code prints elements of A if their index residual from division by 4 equals 0.
Instead of i%4==0 you may enter i%4==1 or 2 or 3 if you need different offset.
A = [0,1,2,3,4,5,6,7,8,9,10,11,12]
print ([A[i] if i%4==0 else 0 for i in range (len(A))])
[0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 12]
If you want to repeat each fourth value 4 times, try this:
print ( [A[i//4*4] for i in range (len(A))])
[0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12]

Set numpy array elements to zero if they are above a specific threshold

Say, I have a numpy array consists of 10 elements, for example:
a = np.array([2, 23, 15, 7, 9, 11, 17, 19, 5, 3])
Now I want to efficiently set all a values higher than 10 to 0, so I'll get:
[2, 0, 0, 7, 9, 0, 0, 0, 5, 3]
Because I currently use a for loop, which is very slow:
# Zero values below "threshold value".
def flat_values(sig, tv):
"""
:param sig: signal.
:param tv: threshold value.
:return:
"""
for i in np.arange(np.size(sig)):
if sig[i] < tv:
sig[i] = 0
return sig
How can I achieve that in the most efficient way, having in mind big arrays of, say, 10^6 elements?
In [7]: a = np.array([2, 23, 15, 7, 9, 11, 17, 19, 5, 3])
In [8]: a[a > 10] = 0
In [9]: a
Out[9]: array([2, 0, 0, 7, 9, 0, 0, 0, 5, 3])
Generally, list comprehensions are faster than for loops in python (because python knows that it doesn't need to care for a lot of things that might happen in a regular for loop):
a = [0 if a_ > thresh else a_ for a_ in a]
but, as #unutbu correctly pointed out, numpy allows list indexing, and element-wise comparison giving you index lists, so:
super_threshold_indices = a > thresh
a[super_threshold_indices] = 0
would be even faster.
Generally, when applying methods on vectors of data, have a look at numpy.ufuncs, which often perform much better than python functions that you map using any native mechanism.
If you don't want to change your original array
In [2]: a = np.array([2, 23, 15, 7, 9, 11, 17, 19, 5, 3])
In [3]: b = np.where(a > 10, 0, a)
In [4]: b
Out[4]: array([2, 0, 0, 7, 9, 0, 0, 0, 5, 3])
In [5]: a
Out[5]: array([ 2, 23, 15, 7, 9, 11, 17, 19, 5, 3])
From the neural networks from scratch series by sentdex on Youtube, he used np.maximum(0, [your array]) to make all values less than 0 into 0.
For your question I tried np.minimum(10, [your array]) and it seemed to work incredibly fast. I even did it on an array that was 10e6 (uniform distribution generated using 50 * np.random.rand(10000000)), and it worked in 0.039571 seconds. I hope this is fast enough.

TypeError: 'int' object is not iterable

I am trying to have a program look inside multiple lists to see if there are multiple integers in those lists. I received an answer on a previous question I asked to accomplish that task. However a problem arose with that answer and I can not figure out what it is.
Here is the code:
def all_num_in_list(d, numbers):
for n in numbers:
if n not in d:
return False
return True
def all_num_in_any_list(lists, numbers):
for d in lists:
if all_num_in_list(d, numbers):
return True
return False
while a:
try:
for c, row in enumerate(matrix):
if 0 in row:
print("Found 0 on row:", c, "index:", row.index(0))
if 1 not in row:
if all(row[row.index(0)] != 1 for row in matrix):
if all_num_in_any_list([2, 3, 4, 5, 6, 7, 8, 9], [row, box1, all(row[row.index(0)])]):
if all(row[row.index(0)] != 1 for row in matrix):
print ("t")
The error that it draws is:
if all_num_in_any_list([2, 3, 4, 5, 6, 7, 8, 9], [row, box1, all(row[row.index(0)])]):
TypeError: 'int' object is not iterable
Why is this happening, how can it be avoided, and what exactly is this code doing?
Thanks
The first parameter to all_num_in_any_list, [2,3,4,5,6,7,8,9], is a single list, not a
list of lists. When you iterate through it, d is 1, then d is 2, and so forth. When
you pass d as the first parameter to all_num_in_list, it is trying to treat it as a list even though it is an integer.
Here is your matrix, from an earlier question
matrix = [
[0, 0, 0, 5, 0, 0, 0, 0, 6],
[8, 0, 0, 0, 4, 7, 5, 0, 3],
[0, 5, 0, 0, 0, 3, 0, 0, 0],
[0, 7, 0, 8, 0, 0, 0, 0, 9],
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[9, 0, 0, 0, 0, 4, 0, 2, 0],
[0, 0, 0, 9, 0, 0, 0, 1, 0],
[7, 0, 8, 3, 2, 0, 0, 0, 5],
[3, 0, 0, 0, 0, 8, 0, 0, 0],
]
And here is the methods:
def all_num_in_list(d, numbers):
for n in numbers:
if n not in d:
return False
return True
def all_num_in_any_list(lists, numbers):
for d in lists:
if all_num_in_list(d, numbers):
return True
return False
And since you in an earlier question used the numbers, 3,5 and 6 as examples to look at, here is how you check if these numbers are in the matrix above:
all_num_in_any_list(matrix, [3, 5, 6])
Which will return False, as none of the lists in your list of lists will have all these tree numbers, while for example:
all_num_in_any_list(matrix, [0, 1, 9])
will return True, as there is a list that includes these numbers.
all_num_in_any_list extacts elements from lists, which in this case are all integers; then, it passes each integer to all_num_in_list, which is expecting a list instead.
The statement for n in numbers in this code is causing the problem
def all_num_in_list(d, numbers):
for n in numbers:
if n not in d:
return False
return True
The Partial Traceback is
if n not in d
def all_num_in_list(d, numbers):
def all_num_in_any_list(lists, numbers):
if all_num_in_any_list([2, 3, 4, 5, 6, 7, 8, 9], [row, box1, all(row[row.index(0)])]):
TypeError: 'int' object is not iterable
So in function all_num_in_any_list you are already iterating for d in lists over the list lists to get integers which is passed to all_num_in_list. But here while trying to compare n with an atom d, is where the Error Happened.
Think Over?
Did you intend to do an integer comparition like n != d instead of if n not in d
.
Note::: Next Time please post the Complete Traceback

Categories

Resources