Given the following problem,
Input
lis = ['0-10,000, 10,001-11,000, 11,001-12,000']
Output:
['0-10,000','10,001-11,000', '11,001-12,000']
Create a function such that, it should avoid if there's a single range in the list but split the ranges if there are multiple ranges in the list.
Can anybody help me with this problem, I can't even think of any method.
First build a string from the list of elements, then split the string with the specified ", ".
lis = ['0-10,000, 10,001-11,000, 11,001-12,000']
print(''.join(lis).split(", "))
I have tried this :
lis = ['0-10,000, 10,001-11,000, 11,001-12,000','0-10,001, 10,001-11,000, 11,001-12,000','0-10,011, 10,001-11,000, 11,001-12,000']
def data_clean(x):
v = []
for i in range(len(x)):
v.append(x[i].split(", "))
return v
Here it is how the output is :
[['0-10,000', '10,001-11,000', '11,001-12,000'],
['0-10,001', '10,001-11,000', '11,001-12,000'],
['0-10,011', '10,001-11,000', '11,001-12,000']]
Related
I'm a freshie. I would like to convert a numeric string into int from a sublist in Python. But not getting accurate results. 😔
countitem = 0
list_samp = [['1','2','blue'],['1','66','green'],['1','88','purple']]
for list in list_samp:
countitem =+1
for element in list:
convert_element = int(list_samp[countitem][0])
list_samp[countitem][1] = convert_element
You can do it like this:
list_samp = [['1','2','blue'],['1','66','green'],['1','88','purple']]
me = [[int(u) if u.isdecimal() else u for u in v] for v in list_samp]
print(me)
The correct way to do it:
list_samp = [['1','2','blue'],['1','66','green'],['1','88','purple']]
list_int = [[int(i) if i.isdecimal() else i for i in l] for l in list_samp]
print(list_int)
Let's go through the process step-by-step
countitem = 0
list_samp = [['1','2','blue'],['1','66','green'],['1','88','purple']]
#Let's traverse through the list
for list in list_samp: #gives each list
for i in range(len(list)): # get index of each element in sub list
if list[i].isnumeric(): # Check if all characters in the string is a number
list[i] = int(list[i]) # store the converted integer in the index i
Im new to python and hit a wall with my last print in my program
I got a list of numbers created with math int(numbers that when printed looks like this
[0, 0, 0, 0] #just with random numbers from 1 - 1000
I want to add text in front of every random number in list and print it out like this
[Paul 0 Frederick 0 Ape 0 Ida 0]
Any help would be appreciated. Thanks !
Sounds like you want to make a dictionary. You could type:
d = dict()
d["Paul"] = random.randint(1,100)
....
print(d)
#output: {"Paul":1, "Fredrick":50, "Ape":25, "Ida":32}
Alternatively there is nothing stopping you from using strings and integers in the same list! Python is not strongly statically typed.
If you have a list of numbers [45,5,59,253] and you want to add names to them you probably need a loop.
nums = [45,5,59,253]
names = ["Paul", "Frederick", "Ape", "Ida"]
d = dict()
i = 0
for n in nums:
d[names[i]] = n
i+=1
or if you wanted a list
nums = [45,5,59,253]
names = ["Paul", "Frederick", "Ape", "Ida"]
list = [x for y in zip(names, nums) for x in y]
You'd have to turn your random integers into strings and add them to the text (string) you want.
Example:
lst=[]
x = str(randint(0,1000))
text = 'Alex'
final_text = text+' '+x
lst.append(final_text)
Just added the space like in your example. It'll just be a little more complex to access the numbers if you do it this way.
I have a list/string. And I would like to split it into pairs and separate them by parenthesis in the same list as output. How do I do that?
What I tried so far?
ip='MDSYS.SDO_GEOMETRY(2003, NULL, NULL, MDSYS.SDO_ELEM_INFO_ARRAY(1, 1003, 1), MDSYS.SDO_ORDINATE_ARRAY(22027, 22943.23, 22026, 22939, 22025, 22936, 22025.09, 22932, 22027, 22929, 22030, 22926)'
split_string_1 = "MDSYS.SDO_ORDINATE_ARRAY("
split_string_2 = ")"
data = list(map(int, ip.split(split_string_1)[1].split(split_string_2)[0].split(", ")))
result = list(zip(data[:-1], data[1:]))
I get an error saying ValueError: invalid literal for int() with base 10: '22943.23' How do I solve this?
Desired output:
[(22027, 22943.23), (22026, 22939), (22025, 22936), (22025.09, 22932), (22027, 22929), (22030, 22926)]
You can rpartition 2 times with your splitting delimiters:
>>> out = ip.rpartition(split_string_1)[-1].rpartition(split_string_2)[0]
>>> out
"22027, 22943.23, 22026, 22939, 22025, 22936, 22025.09, 22932, 22027, 22929, 22030, 22926"
Then split over ", " and map to floats; lastly take every 2 elements with zip (i.e., odd indices and even indices in parallel) to form the output:
>>> out = list(map(float, out.split(", ")))
>>> out = list(zip(out[::2], out[1::2]))
>>> out
[(22027.0, 22943.23),
(22026.0, 22939.0),
(22025.0, 22936.0),
(22025.09, 22932.0),
(22027.0, 22929.0),
(22030.0, 22926.0)]
Use regex pattern ('\([0-9., ]+\) which will give you all tuples containing interger/float, convert string to tuple using ast.literal_eval(). Finally get list of tuples using list(zip(out[::2], out[1::2])
import ast
import re
out = re.findall('\([0-9., ]+\)', ip)[-1]
out = ast.literal_eval(out)
out = list(zip(out[::2], out[1::2])
print(out)
[(22027, 22943.23),
(22026, 22939),
(22025, 22936),
(22025.09, 22932),
(22027, 22929),
(22030, 22926)]
You almost have it, just replace the int with float, because you've got floating point numbers in your data
data = list(map(float, ip.split(split_string_1)[1].split(split_string_2)[0].split(", ")))
result = list(zip(data[::2], data[1::2]))
print(result)
>> [(22027.0, 22943.23), (22943.23, 22026.0), (22026.0, 22939.0), (22939.0, 22025.0), (22025.0, 22936.0), (22936.0, 22025.09), (22025.09, 22932.0), (22932.0, 22027.0), (22027.0, 22929.0), (22929.0, 22030.0), (22030.0, 22926.0)]
A comment on your splitting:
If you're guaranteed to have a string of that form, you can perhaps just do the following:
1)Get rid of the last ) character, ip = ip[:-1]
2)Split on '(' and take the last part, ip = ip.split("(")[-1]
3)Split this on comma, ip = ip.split(",")
ip = ip[:-1].split("(")[-1].split(",")
data = list(map(float, ip))
result = list(zip(data[::2], data[1::2]))
I suggest you define a method that does the operation, in this case it is returning a generator:
def each_slice(iterable, n=2):
if n < 2: n = 1
i, size = 0, len(iterable)
while i < size-n+1:
yield iterable[i:i+n]
i += n
Once you have your list (letting apart the conversion of string to number):
lst = ['22027', '22943.23', '22026', '22939', '22025', '22936', '22025.09', '22932', '22027', '22929', '22030', '22926']
You can just call the method each_slice(lst):
print(list(each_slice(lst)))
#=> [['22027', '22943.23'], ['22026', '22939'], ['22025', '22936'], ['22025.09', '22932'], ['22027', '22929'], ['22030', '22926']]
Note that this implementation cuts off the reminder elements, for example grouping by five:
print(list(each_slice(lst, n=5)))
#=> [['22027', '22943.23', '22026', '22939', '22025'], ['22936', '22025.09', '22932', '22027', '22929']]
I would like to use a for loop to get inputs for many questions I have to receive.
I managed to make some code, but it seems there should be
a better way.
Maybe I can reduce the number of variables I'm using?
## <Desired Result>
## onset : 3mo
## location : earth
## character : red
checks = ['onset','location','character']
l1 = ['onset','location','character']
l2 = ['onset','location','character']
for i in range(len(checks)):
l2[i] = input(checks[i])
for i in range(len(checks)):
print(l1[i]+" : "+l2[i])
A few observations on your code:
Note that you never actually change l1 so basically it is unnecessary and wherever you use l1 replace with checks.
It is not necessary to define l2 this way as you are overriding all its values anyway, so you could just define l2 = [] and then use append in your loop:
for i in range(len(checks)):
l2.append(input(checks[i]))
Both your loops have exactly the same range, so you could combine them to 1:
for i in range(len(checks)):
l2[i] = input(checks[i])
print(l1[i]+" : "+l2[i])
Now, using list-comprehension and the join method of strings, you could actually reduce this code to 3 lines (and get rid of l1):
checks = ['onset', 'location', 'character']
l2 = [input(x) for x in checks]
print("\n".join(checks[i]+" : "+l2[i] for i in range(len(checks))))
Or more neatly using zip:
print("\n".join(check + " : " + ans for check, ans in zip(checks, l2)))
Lastly, to reduce even one more line (and get rid of l2):
checks = ['onset', 'location', 'character']
print("\n".join(check + " : " + input(check) for check in checks))
We could also avoid using join and use the chance to further reduce to one line (getting rid of checks) using print's extra arguments and list-unpacking:
print(*(check + " : " + input(check) for check in ['onset', 'location', 'character']), sep='\n')
What you are trying to achieve for is done using List comprehensions.
In your case you can do that in a single line.
l2 = [input(x) for x in checks]
You should not initialize the list of desired length and take input for each element. You can use append method to that.
The following code will help you:
checks = ['onset','location','character']
arr = []
for i in checks:
arr.append(input(i + ' : '))
If you want to reduce the number of lines, you can try the following:
arr = [ input(i + ' : ') for i in ['onset','location','character']]
For a truly 1-line solution to your for-loops, you could do your list comprehension like this:
l2 = [(n, print(l1[i]+" : "+n))[0] for i, n in enumerate([input(x + ": ") for x in checks])]
Ouput:
onseta
locationb
characterc
onset : a
location : b
character : c
EDIT
As others mentioned, this is not best practice, so use something like this:
checks = ['onset','location','character']
l2 = [input(f"Check {n}:\n > ") for n in checks]
print(*(f"{j}: {l2[i]}\n" for i, j in enumerate(checks)), sep="")
Output:
Check onset:
> ok
Check location:
> ok
Check character:
> ok
onset: ok
location: ok
character: ok
I have two lists one called src with each element in this format:
['SOURCE: filename.dc : 1 : a/path/: description','...]
And one called base with each element in this format:
['BASE: 1: another/path','...]
I am trying to compare the base element's number (in this case it's 4) with the source element's number (in this case it's 1).
If they match then i want to replace the source element's number with the base element's path.
Right now i can split the source element's number with a for loop like this:
for w in source_list:
src_no=(map(lambda s: s.strip(), w.split(':'))[2])
And i can split the base element's path and number with a for loop like this:
for r in basepaths:
base_no=(map(lambda s: s.strip(), r.split(':'))[1])
base_path=(map(lambda s: s.strip(), r.split(':'))[2])
I expect the new list to look like ( base on the example of the two elements above):
['SOURCE: filename.dc : another/path : a/path/: description','...]
the src list is a large list with many elements, the base list is usually three or four elements long and is only used to translate into the new list.
I hacked something together for you, which I think should do what you want:
base_list = ['BASE: 1: another/path']
base_dict = dict()
# First map the base numbers to the paths
for entry in base_list:
n, p = map(lambda s: s.strip(), entry.split(':')[1:])
base_dict[n] = p
source_list = ['SOURCE: filename.dc : 1 : a/path/: description']
# Loop over all source entries and replace the number with the base path of the numbers match
for i, entry in enumerate(source_list):
n = entry.split(':')[2].strip()
if n in base_dict:
new_entry = entry.split(':')
new_entry[2] = base_dict[n]
source_list[i] = ':'.join(new_entry)
Be aware that this is a hacky solution, I think you should use regexp (look into the re module) to extract number and paths and when replacing the number.
This code also alters a list while iterating over it, which may not be the most pythonic thing to do.
Something like this:
for i in range(len(source_list)):
for b in basepaths:
if source_list[i].split(":")[2].strip() == b.split(":")[1].strip():
source_list[i] = ":".join(source_list[i].split(":")[:3] + [b.split(":")[2]] + source_list[i].split(":")[4:])
just get rid of the [] part of the splits:
src=(map(lambda s: s.strip(), w.split(':')))
base=(map(lambda s: s.strip(), r.split(':')))
>> src
>> ['SOURCE', 'filename.dc', '1', 'a/path/', 'description']
the base will similarly be a simple list
now just replace the proper element:
src[2] = base[2]
then put the elements back together if necessary:
src = ' : '.join(src)
def separate(x, separator = ':'):
return tuple(x.split(separator))
sourceList = map(separate, source)
baseDict = {}
for b in map(separate, base):
baseDict[int(b[1])] = b[2]
def tryFind(number):
try:
return baseDict[number]
except:
return number
result = [(s[0], s[1], tryFind(int(s[2])), s[3]) for s in sourceList]
This worked for me, it's not the best, but a start
So there is one large list that will be sequentially browsed and a shorter one. I would turn the short one into a mapping to find immediately for each item of the first list whether there is a match:
base = {}
for r in basepaths:
base_no=(map(lambda s: s.strip(), r.split(':'))[1])
base_path=(map(lambda s: s.strip(), r.split(':'))[2])
base[base_no] = base_path
for w in enumerate source_list:
src_no=(map(lambda s: s.strip(), w.split(':'))[2])
if src_no in base:
path = base[src_no]
# stuff...