How to find elements in a list is consecutive - python

Hi I have a list [tag1 tag2], I would like to find out whether the number following tag is incremental.
match_atr_value = re.search('(.+)\~(\w+)',each_line)
tags = match_atr_value.group(1).split('.')
print tag
Input:
[tag1 tag2]
[tag1 tag3]
[tag1 tag2 tag4]
Output:
Incremental
Not
Not
"Consecutive integers are integers that follow each other in order"
Is there a simpler way to do it? All I have to do is check if its incremental and if yes I should use them else I should throw an exception.
Thanks

You can extract all the digits followed by tag via re.findall() and then use enumerate() and all() to check if the numbers are consecutive:
import re
l = [
"[tag1 tag2]",
"[tag1 tag3]",
"[tag1 tag2 tag4]"
]
pattern = re.compile(r"tag(\d+)")
for item in l:
numbers = map(int, pattern.findall(item)) # if Python 3: call list() on that
result = all(index == item for index, item in enumerate(numbers, start=numbers[0]))
print(result)
Prints:
True
False
False

tag1val = int(re.search(r'\D*(\d+)', tag1).group(1))
tag2val = int(re.search(r'\D*(\d+)', tag2).group(1))
(tag1val - tag2val) == -1
True
tag3val = int(re.search(r'\D*(\d+)', tag3).group(1))
(tag1val - tag3val) == -1
False
(tag2val - tag3val) == -1
True
If you wanted to stick with regular expressions, you can go this route. If the difference is -1 then the one on the right is 1 greater than the one on the left.

If I were you, I would avoid a regex and do something like below. I get the number from the string, whether it's beginning, end, etc. and then compare it to the previous value and return False if it's not increasing
def isIncreasing( listy ):
prev = 0
for w in listy:
val = [''.join(s) for s in w if s.isdigit()]
cur = int(val[0])
if cur != prev+1:
return False
prev = cur
return True

Related

How to replace all occurrences of "00000" with "0" repeatedly?

I need to repeatedly replace all occurrence of 00000 with 0 in a binary string input.
Although I'm able to achieve it to some extent, I do not know the logic when there are multiple consecutive 00000s like for example:
25 0s should be replaced with one 0
50 0s should be replaced with two 0s
125 0s should be replaced with one 0
Currently I have following code :
new_list = []
c = 0
l = list(s.split("00000"))
print(l)
for i in l:
if i == "00000":
for x in range(l.index(i),l.index(i-3)):
if l[x] != 0:
break
for y in range(0,5):
del l[i-y]
new_list.append(i)
new_list.append("0")
r_list = new_list[0:-1]
r_list= ''.join(map(str, r_list))
print(r_list)
But this will not work for 25 0s.
Also What would be the regex alternative for this ?
To get those results, you would need to repeatedly replace five consecutive zeroes to one zero, until there is no more occurrence of five consecutive zeroes. Here is an example run:
s = "0" * 125 # example input
while "00000" in s:
s = s.replace("00000", "0")
print(s)
As I state in my comment, my best guess at what you're trying to do is that you're trying to repeatedly apply the rule that 50's get replaced with 1, so that, for example, 25 0's get reduced to 00000, which in turn gets reduced to 0. Assuming that's correct:
It's not the most efficient approach, but here's one way to do it:
import re
new = "00000100002000003000000004" + "0"*50
old = ""
while old != new:
old,new = new,re.sub("0{5}","0",new)
print(new) #0100002030000400
Alternatively, here's a method to apply that change in one pass through the array:
s = "00000100002000003000000004" + "0"*50
stack,ct = ['#'],[-1]
i = 0
while i < len(s):
if s[i] == stack[-1]:
ct[-1] += 1
i+=1
elif ct[-1] >= 5:
q,r = divmod(ct[-1],5)
ct[-1] = q+r
else:
stack.append(s[i])
ct.append(1)
i+=1
while ct[-1] >= 5:
q,r = divmod(ct[-1],5)
ct[-1] = q+r
ans = "".join(c*k for c,k in zip(stack[1:],ct[1:]))
print(ans)
PyPI regex supports recursion. Something like this could do:
import regex as re
s = re.sub(r"0000(?:(?0)|0)", "0", s)
See this Python demo at tio.run or the regex demo at regex101
At (?0) or alternatively (?R) the pattern gets pasted (recursed).

How can I assign positives and negatives to a string?

I'm trying to create this code so that when variable J is present, it is a positive number, but if H is present, it is a negative number. Here is my code.
record = ['1J2H']
def robot_location(record: str):
if J in record:
sum()
if H in record:
** I dont know how to subtract them**
print(robot_location(record)
So if record = [1J2H] then the output should be ((+1)+(-2)) = -1 should be the output... how can I do that?? Somebody pls help explain this.
You need to iterate over string inside list, check char by char and asume thats always length of string will be odd
record = ['1J2H']
def robot_location(record: str):
total = 0
aux_n = 0
for a in record:
if a.isnumeric():
aux_n = int(a)
else:
if a == 'H':
total = total + aux_n*-1
else:
total = total + aux_n
aux_n = 0
return total
print(robot_location(record[0]))
Here is a concise way to do this via a list comprehension:
record = '1J2H'
nums = re.findall(r'\d+[JH]', record) # ['1J', '2H']
output = sum([int(x[:-1]) if x[-1] == 'J' else -1*int(x[:-1]) for x in nums])
print(output) # -1
One way to do that is by using iter and converting the string into an iterable, that allows to use next which moves the iteration to the next item meaning that if one simply iterates over it it will get moved to the next item and then if one uses next it will return the current value where the "pointer"? is and move it to the next value so the next iteration with a for loop (list comprehension in this case) will get the next value, meaning that the loop will return only the numbers while next will return only the letters:
lst = ['1J2H']
def robot_location(record: str):
record = iter(record)
numbers = [int(i) if next(record) == 'J' else -int(i) for i in record]
return sum(numbers)
print(robot_location(lst[0]))
You could modify a string like s = '1J2H' to '1+2*-1+0' and let Python evaluate it:
result = eval(s.replace('J', '+').replace('H', '*-1+') + '0')

How can I find a specific pattern in a list?

Given a list of numbers containing either 0's, 1's, or -1's, how can I find the longest portion of the list that starts with a +1 and ends with a -1.
For example, [0,0,1,1,1,-1,-1,-1,0] : The longest portion is 6 due to the portion of the list [1,1,1,-1,-1,-1].
For example, [1,-1,0,1,-1,-1,-1] : The longest portion is 4 due to the portion of the list [1,-1,-1,-1]. Note that had the original list only been the first 3 elements (e.g., [1,-1,0]), then the correct answer would have been 2 [1,-1].
Also, the list cannot be broken with a 0 and it can only alternate from +1 to -1 once. In other words [+1,-1,+1,-1] is still only 2.
Thank you
You need has two bool(previous_has_one exist, previous_has_neg_one) to record them exist or not.
def getLongestPortion(l):
maxx = 0
curMax = 0
JustHadOne = False
JustHadNeg = False
for i in range(len(l)):
if(l[i]==1):
if(JustHadNeg):
curMax = 0
curMax += 1
JustHadOne = True
JustHadNeg = False
elif(l[i]==-1 and JustHadOne):
curMax += 1
maxx = max(maxx,curMax)
JustHadNeg = True
else:
JustHadOne = False
JustHadNeg = False
curMax=0
return maxx
l = [1,-1,-1,0,1,1,-1,-1]
print(getLongestPortion(l))
Here's a regex solution. First I change a list like [1, -1, 0, 1, -1, -1, -1] to a string like 'ab abbb', then I search for 'a+b+', then take the maximum length of the matches:
import re
max(map(len, re.findall('a+b+', ''.join(' ab'[i] for i in l))))

Returning something other than -1 index

Hi I would like to know how I can have my code below return the following given the input
split_sentence("doghellomeyayahell")
return
["dog","hellomeyayahell",""]
instead of
['dog', 'hellomeyayahel', 'l']
I know the problem is that since the thing cannot find the 'hello' string it returns the -1 index. If possible how would I make it so the above would work?
def split_sentence(s):
lst = []
first = s.find('hello')
firsts = s[0:first]
third = s.find('hello', first +2, len(s))
thirds = s[third:len(s)]
second = s[first:third]
lst.append(firsts)
lst.append(second)
lst.append(thirds)
return lst
You can't make it return something else, so you have to test the return value.
if third == -1:
third = len(s)
thirds = s[third:]
You can also use try/except with index:
try:
third = s.index('hello', first + 2)
except:
third = len(s)

Check whether there are duplicate values (which is > 0) in a list in Python

I want to check whether there are duplicate elements which is more than 0 in an array list.
if [1,0,0,0,1,2] = true
if [0,0,0,0,0,0] = false
How can I get this result?
I guess OP wants to handle natural numbers only. Try this:
def is_duplicated_natural_numbers(input):
# make it >0
natural_numbers_list = list(filter(lambda x: x > 0, input))
# remove duplicates
set_list = list(set(natural_numbers_list))
# if natural_numbers_list == set_list, no natural numbers duplicates
return natural_numbers_list != set_list
print(is_duplicated_natural_numbers([1,0,0,0,1,2])) # True
print(is_duplicated_natural_numbers([0,0,0,0,0,0])) # False
print(is_duplicated_natural_numbers([1,2,3,4,5,1])) # True
Use a dictionary to keep a count of elements and if an element occurs twice (which is not zero) then your answer is true so just break from the loop.
Try This :
l = [0,0,0,0]
dic = {}
flag = False
for i in l:
if i in dic:
dic[i]+=1
if dic[i]>1 and i!=0:
flag = True
break
else:
dic[i] = 1
print flag
Note : Better ways are there but this one is really simple to understand.

Categories