How to seperate decimal numbers written back to back - python

How would it be possible to seperate a string of values (in my case, only corresponding to roman numeral values) into elements of a list?
'10010010010100511' -> [100, 100, 100, 10, 100, 5, 1, 1,]
I want to create something that goes like:
if it is a zero add it to side
if it's not a zero create a new element for it

You were on the right track with zeros, you have to notice that every base roman numeral is either a 1 or 5 followed by some amount of zeros. You can represent that as a very simple regex.
import re
s = '10010010010100511'
pattern = "[1|5]0*"
matches = re.finditer(pattern=pattern, string=s)
l = [match[0] for match in matches]
print(l) # ['100', '100', '100', '10', '100', '5', '1', '1']
If for some reason you don't want to use regex, you can simply iterate over each character using the same principle:
string = '10010010010100511'
lst = []
for char in string:
if char in ['1', '5']:
lst.append(char)
elif char == '0':
lst[-1] += '0'
print(lst) # ['100', '100', '100', '10', '100', '5', '1', '1']

Code:
s='10010010010100511'
d=[]
c=0 #introducing this new varible just to know from where
for i in range(len(s)): ##Here basic idea is to check next value
if i+1 <len(s):
if s[i+1]!='0': #if NEXT value is not zero thn
d.append(s[c:i+1]) #get string from - to and add in d list
c=len(s[:i+1])
else:
d.append(s[-1])
d
Output:
['100', '100', '100', '10', '100', '5', '1', '1']

Related

Generated List consists of [Apparantly] unaccounted whitespaces in this code snippet

For a routine question on python programming, I was asked to generate a list of string sliced from one string (let's call it as target_string), with the length of each sliced string increasing from 1 to the length of string.
For example, if target_string is '123', I would have to generate the list like this : ['1', '2', '3', '12', '23', '123'].
For this, I wrote a code snippet that was something like this:
target_string = raw_input("Target String:")
length = len(target_string)
number_list = []
for i in range(length):
for j in range(length):
if j + i <= length:
number_list.append(target_string[j:j + i])
print(number_list)
On execution of this the result was:
Target String:12345
['', '', '', '', '', '1', '2', '3', '4', '5', '12', '23', '34', '45', '123', '234', '345', '1234', '2345']
The first thing I noticed is that the list consists of whitespaces as elements, and the number of whitespaces is equal to the length of the target_string. Why does this happen? Any kind of clarification and help is welcome.
P.S: I have a temperory workaround to generate the list that I need:
target_string = raw_input("Target String:")
length = len(target_string)
number_list = []
for i in range(length):
for j in range(length):
if j + i <= length:
number_list.append(target_string[j:j + i])
number_list.append(target_string)
del number_list[0:length]
target_list = [int(i) for i in number_list]
print(target_list)
Also feel free to suggest any changes or modifications to this, or any approach you would feel is more efficient and pythonic. Thanks in advance.
Edit: This is implemented in Pycharm, on Windows 10 , using Python 2.7, but please feel free to give the solutions in both the Python 2.7 and 3.X versions.
You can use itertools.combinations, then get the ones that the indexes are continuously adding 1, use ''.join(..) for converting it o a string and add it using .extend(..):
Python 2.7:
import itertools
target_string = raw_input("Target String:")
l=[]
for i in range(1,len(target_string)+1):
l.extend([''.join(i) for i in itertools.combinations(target_string,i) if all(int(y)-int(x)==1 for x, y in zip(i, i[1:]))])
print l
Output:
['1', '2', '3', '12', '23', '123']
Python 3.x:
import itertools
target_string = input("Target String:")
l=[]
for i in range(1,len(target_string)+1):
l.extend([''.join(i) for i in itertools.combinations(target_string,i) if all(int(y)-int(x)==1 for x, y in zip(i, i[1:]))])
print(l)
Output:
['1', '2', '3', '12', '23', '123']
Explaining why you got whitespaces in your code snippet.
Have a look at the loop part:
for i in range(length):
for j in range(length):
if j + i <= length:
number_list.append(target_string[j:j + i])
Here, both i and j gets initiated with 0.
So when we decode it, it comes like:
i = 0:
j=0:
0+0 < length
number_list.append(for i in range(length):
for j in range(length):
if j + i <= length:
number_list.append(target_string[0:0 + 0])) --> ['']
and so on.....

How to replace elements in list when condition is met [duplicate]

This question already has answers here:
Create a new list from a list when a certain condition is met
(4 answers)
Closed 6 years ago.
Right now, I am struggling to find a proper answer. Let's say we have this list:
['12', '50', '12', '7', '7', '3', '4', '10', '19', '12']
As you can see, it's a list of strings. I could map this to a list of ints, but I won't, because I need to change them back to strings anyway. On the other hand, it would be handy if I would do it because I need to check for a condition.
What do I need? --> I need to change the elements in the list when a certain condition is met. So, for example: if a list in the element is greater than 10, I need to change the element to a certain character like a plus (+) or a minus (-)
Eventually, my list should be something like this:
['+', '+', '+', '-', '-', '-', '-', '+', '+', '+']
So, the concept in my head right now is:
Don't convert the string to an int, because I will need to transform them to strings anyway (hence the special characters I was talking about).
I need to use a for loop, because I want to check every element
I'd probably need to use a loop like this:
for score in scores:
if score == "5": # check if element is a 5
score == "+" # make it a plus
else:
score == "-" # make it a minus
Problem: this doesn't work and I don't even know if this is the right way. I can use score[0] and get every element in the list like this, but this wouldn't be efficient nor generic, or would it? What is the best way to transform elements in a list when a certain condition is met?
Can someone point in me the right direction please?
Try this (assuming you want 10 as the cutoff)
li = ['12', '50', '12', '7', '7', '3', '4', '10', '19', '12']
new_list = ['+' if int(el)>10 else '-' for el in li]
You can do:
Initial l = ['12', '50', '12', '7', '7', '3', '4', '10', '19', '12']
Map to int: l = list(map(int, l))
Then: a = ['+' if i>10 else '-' for i in l]
a = ['+', '+', '+', '-', '-', '-', '-', '-', '+', '+']
It doesn't work because:
A for loop in Python creates a new local variable, and
You used == instead of =.
Try this approach:
for index, score in enumerate(scores):
if scores[index] == "5": # check if element is a 5
scores[index] = "+" # make it a plus
else:
scores[index] = "-" # make it a minus
A quick side note: your question asks for "greater/smaller" then but your example uses ==. If you want to test for greater or smaller you have to convert the elements to int.

Finding the index of the first element of a list in another list

main_list = ['4', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
my_list = ['4', '5', '6']
My question is, how to find index of my_list in main_list?
The integers in my_list must be in consecutive order in main_list.
I tried using main_list.index(my_list[0]) but if there are more than one of a specific element, it returns the wrong index number. The result I need to get is 4, however with main_list.index(my_list[0]) it'll just give 0 as its index.
If there is any need for clarification, I can edit the post with additional details. Sorry, English is not my first language.
Try something like this
for i in range(len(main_list)-len(my_list)):
if main_list[i:i+len(my_list)] == my_list:
index = i
break
This should work for all possible types that could go in the lists.
You can convert both lists into a string using join() function and iteratively compare the strings to find a match.
EDIT: Made a change for it two work for multi-digit numbers. Added a float case as well.
For example:
main_list = ['4', '1', '2', '3', '40.1', '52', '61', '7', '8', '9', '10']
my_list = ['40.1', '52', '61']
index = -1
for i in range(len(main_list)):
if '#'.join(main_list[i:i+len(my_list)]) == '#'.join(my_list):
index = i
break
print(index)
If you would like an algorithm solution:
def Find(haystack, needle):
n, h = len(needle), len(haystack)
assert n <= h
for i in range(h):
if h - i <= n: break
count = 0
for i_, j in zip(range(i, i + n), range(n)):
if haystack[i_] == needle[j]:
count += 1
if count == n: return i
return -1
A much more effective one liner :
print ','.join(main_list).find(','.join(my_list)) - ''.join(main_list).find(''.join(my_list))
Converts them to strings with the elements separated by commas, finds the occurrence, then subtracts the occurrence found when the commas aren't there, and you have your answer.

python - looping through values in a string

I'm trying to get numerous values out of a pretty complex string that looks like this -
s = '04/03 23:50:06:242[76:Health]: (mem=188094936/17146904576) Queue Size[=:+:-] : Core[Compiler:0:0:0,HighPriority:0:74:74,Default:6:1872:1874,LowPriority:0:2:2]:Special[Special:0:2:2]:Event[Event:0:0:0]:Comm[CommHigh:0:1134:1152,CommDefault:0:4:4]'
These are the values I need to scan for -
list = ['Compiler', 'HighPriority', 'Default', 'LowPriority', 'Special', 'Event', 'CommHigh', 'CommDefault']
My intention is to get the 3 numbers after each string so in the example of HighPriority I would get [0, 74, 74] which I can then do something with each item.
I've used the below but it doesn't account for when the end of the string isn't a comma.
def find_between( s, first, last ):
try:
start = s.index( first ) + len( first )
end = s.index( last, start )
return s[start:end]
except ValueError:
return ""
for l in list:
print l
print find_between( s, l + ':', ',' ).split(':')
Edit, if you really want to avoid regexes, your approach works with a minor tweak (I renamed list to l to avoid shadowing the built in type):
from itertools import takewhile
from string import digits
def find_between(s, first):
try:
start = s.index(first) + len(first)
# Keep taking the next character while it's either a ':' or a digit
# You can also just cast this into a list and forget about joining and later splitting.
# Also, consider storing ':'+digits in a variable to avoid recreating it all the time
return ''.join(takewhile(lambda char: char in ':'+digits, s[start:]))
except ValueError:
return ""
for _ in l:
print _
print find_between(s, _ + ':').split(':')
This prints:
Compiler
['0', '0', '0']
HighPriority
['0', '74', '74']
Default
['6', '1872', '1874']
LowPriority
['0', '2', '2']
Special
['0', '2', '2']
Event
['0', '0', '0']
CommHigh
['0', '1134', '1152']
CommDefault
['0', '4', '4']
However, this really is a task for regex, and you should try to get to know the basics.
import re
def find_between(s, word):
# Search for your (word followed by ((:a_digit) repeated three times))
x = re.search("(%s(:\d+){3})" % word, s)
return x.groups()[0]
for word in l:
print find_between(s, word).split(':', 1)[-1].split(':')
This prints
['0', '0', '0']
['0', '74', '74']
['6', '1872', '1874']
['0', '2', '2']
['0', '2', '2']
['0', '0', '0']
['0', '1134', '1152']
['0', '4', '4']
check this:
import re
s = '04/03 23:50:06:242[76:Health]: (mem=188094936/17146904576) Queue Size[=:+:-] : Core[Compiler:0:0:0,HighPriority:0:74:74,Default:6:1872:1874,LowPriority:0:2:2]:Special[Special:0:2:2]:Event[Event:0:0:0]:Comm[CommHigh:0:1134:1152,CommDefault:0:4:4]'
search = ['Compiler', 'HighPriority', 'Default', 'LowPriority', 'Special', 'Event', 'CommHigh', 'CommDefault']
data = []
for x in search:
data.append(re.findall(x+':([0-9]+:[0-9]+:[0-9]+)', s))
data = [map(lambda x: x.split(':'), x) for x in data] # remove :
data = [x[0] for x in data] # remove unnecessary []
data = [map(int,x) for x in data] # convert to int
print data
>>>[[0, 0, 0], [0, 74, 74], [6, 1872, 1874], [0, 2, 2], [0, 2, 2], [0, 0, 0], [0, 1134, 1152], [0, 4, 4]]
This will get you all the groups, provided the string is always well formed:
re.findall('(\w+):(\d+):(\d+):(\d+)', s)
It also gets the time, which you can easily remove from the list.
Or you can use a dictionary comprehension to organize the items:
matches = re.findall('(\w+):(\d+:\d+:\d+)', s)
my_dict = {k : v.split(':') for k, v in matches[1:]}
I used matches[1:] here to get rid of the spurious match. You can do that if you know it will always be there.

Iterating between 2 lists

I have 2 lists: 1 of which is a lists of lists. They are as follows-
lists_of_lists = ['1', '4', '7', '13', '16', '21', '32', '36'],['3', '6', '8', '14', '22', '26', '31', '40']
just_a_list =['THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOG', 'IWOULDLOVETOGETOVERWITHTHISASSOONASPOSSIBLE']
The lists_of_lists are used for slicing the elements of just_a_list such that:
['1', '4', '7', '13', '16', '21', '32', '36'] would slice the string 'THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOG' as follows
'1' - '4' - 'HEQU'
'7' - '13' - 'KBROWNF'
'16' - '21' - 'JUMPED'
'32' - '36' - 'ZYDOG'
points to note-
Each list in list_of_lists will have an even number of numbers.
The list at i'th position in list_of_lists will belong to the
string present at the i'th position in just_a_list.
Please help me out as to how do I carry out the process described above..
Thanks
Use zip() to combine the string and slice lists, then use a zip() plus iter() trick to pair the start and stop values:
for slicelist, text in zip(lists_of_lists, just_a_list):
for start, stop in zip(*([iter(slicelist)]*2)):
print(text[int(start):int(stop) + 1])
Note that we have to add 1 to the stop index, as your appear to need it to be inclusive, while in Python the stop index is exclusive.
This gives:
>>> for slicelist, text in zip(lists_of_lists, just_a_list):
... for start, stop in zip(*([iter(slicelist)]*2)):
... print(text[int(start):int(stop) + 1])
...
HEQU
KBROWNF
JUMPED
YDOG
ULDL
VETOGET
HTHIS
ONASPOSSIB
If I understand you right:
>>> ls = just_a_list =['THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOG', 'IWOULDLOVETOGETOVERWITHTHISASSOONASPOSSIBLE']
>>> ls[0]
'THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOG'
# so we do
# your index was off by one
>>> ls[0][1:5]
'HEQU'
>>> ls[0][7:14]
'KBROWNF'

Categories

Resources