pattern matching in a list in python - python

i have a list :
l= [3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 3, 4]
now i want to check if while going from index(x) to index(x+1) does it fall in any of the following pattern_list
pattern=['03','34','46','60'].
If that exists then make another list k where values are stored in the form 0 or 1, meaning 0 no pattern and 1 pattern exists.
e.g.
k=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]
I tried this :
s_1_list=[]
str_1 = ""
for i in l:
str_1 += str(i)
regexList_1= ['03','34','46','60']
for regex in regexList_1:
s_1 = str_1.count(regex)
s_1_list.append(s_1)
print("Number of times " + regex + " repeated= ", s_1)
output :
Number of times 03 repeated= 0
Number of times 34 repeated= 1
Number of times 46 repeated= 0
Number of times 60 repeated= 0
but this doest give me a new list as desired with the following output, can anyone suggest how to proceed ?

Loop over s1, checking if any of the patterns are found at that index, and put 0 or 1 in the result list.
s_1_list = [1 if str_1[i:i+2] in regexList_1 else 0 for i in range(len(str_1)-1)]

Here is my solution.
pattern = ['03', '34', '46', '60']
l = [3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 3, 4]
k = []
for i in range(len(l) - 1):
temp = ''
temp += str(l[i]) + str(l[i + 1])
if temp in pattern:
k.append(1)
else:
k.append(0)
print(k)

Related

Finding the number of substrings which sum is equal to m

I'm trying some python and I got this:
I have a string S='3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2' and m=9.
I want to know how many substrings with with sum equals m there are.
So with S and m above i whould get 7 as a result as:
'3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2'
_'0,4,0,3,1,0,1,0'_____________
_'0,4,0,3,1,0,1'_______________
___'4,0,3,1,0,1,0'_____________
____'4,0,3,1,0,1'_______________
____________________'0,0,5,0,4'_
______________________'0,5,0,4'_
_______________________'5,0,4'_
Now, the code i came up with does something like that
def es1(S,m):
c = 0
M = 0
ls = StringToInt(S)
for x in ls:
i= ls.index(x)
for y in ls[i+1:]:
M = x + y
if M == m:
c += 1
M = 0
break
if M > m:
M = 0
break
else:
continue
return c
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
Where StringToInt obv gives me a list of int to work with.
The thing I don't get is where my concept is wrong since es1 returns 3
You could use zip to progressively add numbers to a list of sums and count how many 9s you have at each pass:
S = '3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2'
m = 9
numbers = list(map(int,S.split(",")))
result = 0
sums = numbers
for i in range(len(numbers)):
result += sums.count(m)
sums = [a+b for a,b in zip(sums,numbers[i+1:]) ]
print(result)
For a more "functional programming" approach, you can use accumulate from itertools:
from itertools import accumulate
numbers = list(map(int,S.split(",")))
ranges = (numbers[i:] for i in range(len(numbers)))
sums = (accumulate(r) for r in ranges)
result = sum( list(s).count(m) for s in sums )
print(result)
To explain how this works, let's first look at the content of ranges, which are substrings from each position up to the end of the list:
[3, 0, 4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 0, 5, 0, 4, 2]
[0, 0, 5, 0, 4, 2]
[0, 5, 0, 4, 2]
[5, 0, 4, 2]
[0, 4, 2]
[4, 2]
[2]
When we make a cumulative sum of the rows (sums), we obtain the total of values starting at the position defined by the row number and for a length defined by the column number. e.g. line 5, column 3 represents the sum of 3 values starting at the fifth position:
[3, 3, 7, 7, 10, 11, 11, 12, 12, 13, 13, 13, 18, 18, 22, 24]
[0, 4, 4, 7, 8, 8, 9, 9, 10, 10, 10, 15, 15, 19, 21]
[4, 4, 7, 8, 8, 9, 9, 10, 10, 10, 15, 15, 19, 21]
[0, 3, 4, 4, 5, 5, 6, 6, 6, 11, 11, 15, 17]
[3, 4, 4, 5, 5, 6, 6, 6, 11, 11, 15, 17]
[1, 1, 2, 2, 3, 3, 3, 8, 8, 12, 14]
[0, 1, 1, 2, 2, 2, 7, 7, 11, 13]
[1, 1, 2, 2, 2, 7, 7, 11, 13]
[0, 1, 1, 1, 6, 6, 10, 12]
[1, 1, 1, 6, 6, 10, 12]
[0, 0, 5, 5, 9, 11]
[0, 5, 5, 9, 11]
[5, 5, 9, 11]
[0, 4, 6]
[4, 6]
[2]
In this triangular matrix each position corresponds to the sum of one of the possible substrings. We simply need to count the number of 9s in there to get the result.
The above solutions will perform in O(N^2) time but, if you are concerned with performance, there is a way to obtain the result in O(N) time using a dictionary. Rather than build the whole sub arrays in the above logic, you could simply count the number of positions that add up to each sum. Then, for the sum at each position, go directly to a previous sum total that is exactly m less to get the number of substrings for that position.
from itertools import accumulate
from collections import Counter
numbers = map(int,S.split(","))
result = 0
sums = Counter([0])
for s in accumulate(numbers):
result += sums[s-m]
sums[s] += 1
print(result)
Note that all these solutions support negative numbers in the list as well as a negative or zero target.
As mentioned by others, your code only looks at sums of pairs of elements from the list. You need to look at sublists.
Here is a O(n) complexity solution (i.e. it's efficient since it only scans though the list once):
def es2(s, m):
s = string_to_int(s)
c = 0
# index of left of sub-list
left = 0
# index of right of sub-list
right = 0
# running total of sublist sum
current_sum = 0
while True:
# if the sub-list has the correct sum
if current_sum == m:
# add as many zeros on the end as works
temp_current_sum = current_sum
for temp_right in range(right, len(s) + 1):
if temp_current_sum == m:
c += 1
if temp_right<len(s):
temp_current_sum += s[temp_right]
else:
break
if current_sum >= m:
# move the left end along and update running total
current_sum -= s[left]
left += 1
else:
# move the right end along and update running total
if right == len(s):
# if the end of the list is reached, exit
return c
current_sum += s[right]
right += 1
def string_to_int(ls):
s = [int(x) for x in ls.split(',')]
return s
if __name__ == '__main__':
print(es2('3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2', 9))
This is the code you are looking for man. i felt looking by position was better for this problem so I did it and it worked.
def es1(S,m):
c = 0
M = 0
ls = StringToInt(S)
for i in range(0, len(ls)):
M = 0
for x in range(i, len(ls)):
M += ls[x]
if M == m:
c += 1
elif M >= m:
break
return c
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
print(es1("3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2", 9))
OUTPUT:
7
Your code counts how many pairs of numbers there are in the String S which together give m while you actually want to test all possible substrings.
You could do something like:
numbers = [3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2]
m = 9
c = 0
for i in range(len(numbers)):
for j in range(len(numbers)-i):
sum = 0
for k in numbers[i:i+j]:
sum += k
if sum == m:
c += 1
print(c)
Output:
7
EDIT! ->This Code is actually all possible subsets, not sublists. I am going to leave this here though in case this solution is helpful to anyone who visits this question.
This code gets every solution. If you take a look in the function es1() the result variable is huge list of arrays with all the possible solutions.
import itertools
def es1(S,m):
result = [seq for i in range(len(StringToInt(S)), 0, -1) for seq in itertools.combinations(StringToInt(S), i) if sum(seq) == m]
return len(result)
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
print(es1("3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2", 9))
OUTPUT:
4608
There are 4608 possible sets that add to the value 9.
s = "3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2"
m = 9
sn = s.replace(",","+") # replace "," with "+"
d = {} # create a dictionary
# create list of strings:
# s2 = ["3+0","0+4","4+0".............]
# s3 = ["3+0+4","0+4+0","4+0+3".............]
# .
# .
# .
for n in range(2,len(s.split(","))):
d["s%s"%n] = [sn[i:i+(2*n-1)] for i in range(0,len(sn),2)][:-n+1]
# evaluate whether sum of individual lists equal to m or not, then find out how many such lists are there
l = sum([eval(x)==m for y in d.values() for x in y] )
# remember we didnot add s1, i,e check whether individual string == m or not
l = l+sum([x==m for x in s.split(",")])
print(l)
7

How to edit integers of a list?

So I’m trying to take a list like this:
[1, 2, 3, 8, 15, 4, 12, 8]
And whenever a number is larger than 9 or has two digits, that number has 10 subtracted from it, and 1 is added to the previous number in the list.
So the list would result into this:
[1, 2, 3, 9, 5, 5, 2, 8]
For now, i have something like:
for i in list:
If i in list>= 10
list[i] = list[i] - 10
list[i-1] = list[i-1] + 1
But I’m getting an error from this
Does anyone know how to do this?
We are enumerating the list and as your logic says, if we encounter a number that is bigger than 9, we substract it from 10 and we add 1 to the previous element.
my_list = [1, 2, 3, 8, 15, 4, 12, 8]
for index,item in enumerate(my_list):
if item > 9:
my_list[index] -= 10
if index > 0:
my_list[index-1] += 1
print(my_list) # [1, 2, 3, 9, 5, 5, 2, 8]
data = [1, 2, 3, 8, 15, 4, 12, 8]
count = 0
for item in data:
if item >= 10 :
data[count-1] += 1
data[count] -= 10
count += 1
Output:
[1, 2, 3, 9, 5, 5, 2, 8]
Here it is man, but this only handles if the first item is less than 10 because I did not make the logic for it to check if its the first item, it will crash if the first item in the list is greater than or equal to 10.
x = [1,2,3,8,15,4,12,8]
for i in range(0, len(x)):
if x[i] >= 10:
x[i] = x[i]-10
x[i-1] = x[i-1]+1
print(x)
the output will be
[1, 2, 3, 9, 5, 5, 2, 8]

Finding ordered array in an ordered array

c = [-1, 0, 1, 2, 3, 4]
d = [-1,0,2,3,4,5,6]
a = [-1, 1, 6, 8, 9, 12]
main = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
desired output:
fc = [-1,0,1,2,3],[0,1,2,3,4]
fd = [2,3,4,5,6]
fa = []
I want to find how many times the ordered set is in the larger set given an interval. In my case, I choose 5 since this is for my poker game. Set's won't work since they need to be in order so I don't know what to use.
In my program, I tried using for loops but I'm not getting it.
ns = len(c)-5
nt = range(0,ns)
if ns >= 0:
for n in nt:
templist = c[n:n+5]
I just need a function to compare both lists.
Compare the small lists to slices of main.
c = [-1, 0, 1, 2, 3, 4]
d = [-1,0,2,3,4,5,6]
a = [-1, 1, 6, 8, 9, 12]
main = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
for sublist in [c, d, a]:
l = len(sublist)
i = 0
while i + l <= len(main):
if sublist == main[i:i+l]:
print 'sublist %s matches' % sublist
i = i + 1
Neither pretty nor optimal, but it does what seems to be asked:
c = [-1, 0, 1, 2, 3, 4]
d = [-1, 0, 2, 3, 4, 5, 6]
a = [-1, 1, 6, 8, 9, 12]
main = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
def find_in_order(to_find, to_search, num_to_find):
solutions = []
for bucket in to_find:
bucket_solutions = []
solutions.append(bucket_solutions)
for thing in [bucket[x:x + num_to_find] for x in range(len(bucket) - num_to_find + 1)]:
for section in [main[y:y + num_to_find] for y in range(len(to_search) - num_to_find + 1)]:
if thing == section:
bucket_solutions.append(thing)
return solutions
fc, fd, fa = find_in_order([c, d, a], main, 5)
# fc == [[-1, 0, 1, 2, 3], [0, 1, 2, 3, 4]]
# fd == [[2, 3, 4, 5, 6]]
# fa == []
There's not bounds-checking in this, so it might be brittle. I also don't like how the additions of the magic number 1 are needed to get things to align. If you care about speed, string searches do things like keeping a rolling checksum and only doing comparisons when the checksums match. This is left as an exercise. Also, I'm on:
sys.version
'3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34) \n[GCC 7.3.0]'
Here is a function that I made that might help you. You can pass your list as an argument and it will compare the lists.
main_set = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
c = [-1, 0, 1, 2, 3, 4]
def compare(cmp_array):
new_arrays = []
temp = []
for pos, i in enumerate(cmp_array):
for i2 in range(pos, pos+5):
temp.append(cmp_array[i2])
new_arrays.append(temp)
temp = []
if pos >= len(cmp_array)-5:
break
return_arrays = []
for array in new_arrays:
for pos, i in enumerate(main_set):
match = True
if i == array[0]:
for pos2 in range(pos, pos+5):
if array[pos2-pos] != main_set[pos2]:
match = False
break
if match:
return_arrays.append(array)
return return_arrays
fc = compare(c)
print(fc)

how to find the count the difference back to the previous zero in a list?

I have below list
[7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
and the result list is
[1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
the result obtained by with the below logic
For each value, count the difference back to the previous zero (or the start of the Series,
whichever is closer).
am trying to implement , but not able to get .
So how to find the previous zero position , such that we can get that series ?
I tried below , but somehow it is failing , and it is seems not good solution
import pandas as pd
df = pd.DataFrame({'X': [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]})
#print(df)
df_series = df['X']
print(df_series.iloc[-1])
target_series = pd.Series([])
#print(target_series)
def calculate_value(i,actual_index):
if(df_series.iloc[i-1] == 0):
if(i < 0):
zero_position = i + df_series.size-1
if(actual_index - 0 < zero_position):
target_series[actual_index]=actual_index+1
return
else:
target_series[actual_index]=zero_position
return
else:
target_series[actual_index]=target_series[actual_index]+1
return
else:
if(i+df_series.size != actual_index):
calculate_value(i-1,actual_index)
for i in df.index:
if(df_series[i]==0 and i!=0):
target_series[i]=0
elif(df_series[i]!=0 and i==0):
target_series[i]=1
else:
calculate_value(i,i)
print(target_series)
If you want a Pandas one-liner solution:
import pandas as pd
s = pd.Series([7, 2, 0, 3, 4, 2, 5, 0, 3, 4])
(s.groupby(s.eq(0).cumsum().mask(s.eq(0))).cumcount() + 1).mask(s.eq(0), 0).tolist()
Output:
[1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
If you stick to the list you can get your result quite easily:
l = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
i = 0
r = []
for element in l:
if element != 0:
i += 1
else:
i = 0
r.append(i)
r
#[1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
Here is a working solution for you:
a = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
b = []
z_pos = -1
for i, n in enumerate(a):
if n == 0:
z_pos = i
b.append(i - z_pos)
print(b) # [1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
It does not use anything too fancy so I explaining its internal workings is unnecessary I think. If however there is something that is not clear to you let me know.
If you want to use python only, here is the solution:
a = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
z = None
b = []
for i in range(len(a)):
if a[i] != 0 and z== None:
b.append(i+1)
elif a[i] == 0:
b.append(0)
z = 0
else:
z += 1
b.append(z)
b is the required list.
Here is how to do it with a standard list, not Pandas dataframe, but the logic is the same
arr = [7,2,0,3,4,5,1,0,2]
arr2 = []
counter = 1
for item in arr:
if(item==0):
counter = 0
arr2.append(counter)
counter+=1
print(arr2)
You can see the code working here.
Some explanations:
What you want is a sort of counter between two 0 in your array.
So you loop over your array, and each time you encounter a 0 you reset your counter, and you insert the value of your counter each iteration of the loop.
If you are a fan of shortness instead of readability or effectiveness, you can also roll with this:
a = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
distances = [([0]+a)[:idx][::-1].index(0) for idx in range(1, len(a)+2)][1:]
Which gives the desired result:
print(distances)
>> [1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
Solution with no for loops or apply, just some pandas groupby fun.
We use
df = pd.DataFrame({'X': [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]})
# make a new column with zeros at zeros and nans elsewhere
df = df.assign(idx_from_0=df.loc[df.X==0])
nul = df['idx_from_0'].isnull()
df.assign(idx_from_0=nul.groupby((nul.diff() == 1).cumsum()).cumsum())
Out[1]:
X idx_from_0
0 7 1.0
1 2 2.0
2 0 0.0
3 3 1.0
4 4 2.0
5 2 3.0
6 5 4.0
7 0 0.0
8 3 1.0
9 4 2.0
The cumsum forward fill add one was taken from this answer.

Split list into smaller lists based on values?

Say I have a list: [1, 2, 3, 4, -1, 5, 6, 7, -1, 0, 0, 3, 2, 1]
I want to split this list into using values -1 or 0, 0 as a delimiter:
[[1, 2, 3, 4], [5, 6, 7], [], [3, 2, 1]]
(Note the empty 3rd list)
How would I achieve this? My current solution is just a trivial loop but I'm wondering if theres a more pythonic solution (using list comprehensions) for delimiters of any length?
Current solution as requested (messy and hacky :P)
string = '|'.join([str(x) for x in data]).replace('-1', ',').replace('0|0', ',')
buckets = [x.split('|') if y for x in string.split(',')]
It's not trivial, but you can done it like this:
my_list = [1, 2, 3, 4, -1, 5, 6, 7, -1, 0, 0, 3, 2, 1]
my_list = ','.join(map(str, my_list))
my_list = [x.split(',') for y in my_list.split('0,0,') for x in y.split(',-1,')]
my_list = [map(int, x) if x != [''] else [] for x in my_list]
Using simple for loop and check conditions
Code:
lst = [1, 2, 3, 4, -1, 5, 6, 7, -1, 0, 0, 3, 2, 1,-1,0]
output_lst = []
check = 0
sample=[]
for val in lst:
if val == -1 :
output_lst.append(sample)
check = 0
sample = []
continue
if val == 0 :
if check ==1 :
output_lst.append(sample[:-1])
check = 0
sample = []
continue
check = 1
sample.append(val)
if check ==1:
output_lst.append(sample)
print output_lst
Output:
[[1, 2, 3, 4], [5, 6, 7], [], [3, 2, 1], [0]]
Try this
use one iteration for to do it.
ar = [1, 2, 3, 4, -1, 5, 6, 7, -1, 0, 0, 3, 2, 1]
data = ', '.join(map(str, ar))
import re
data = re.split(", -1,| 0, 0,",data)
bucket = []
import ast
for y in data:
hac = ast.literal_eval("["+y+"]")
bucket.append(hac)
print bucket

Categories

Resources