I have a python list that looks like alist = ['4', '1.6', 'na', '2e-6', '42']. If i want to remove the quotes from this and make it look like [4, 1.6, na, 2e-6, 42], normally i use the following code :
alist = [float(x) if type(x) is str else None for x in alist]
But this time, as I have the string 'na' as one of the elements in the list, this line of code will not work. Is there an elegant way to do this in python?
Assuming you are happy to replace the value 'na' with None, or more generally, any non-float looking text with None, then you could do something like:
def converter(x):
try:
return float(x)
except ValueError:
return None
alist = [converter(x) for x in alist]
This will convert anything to float that it can. So, as it stands, this will also convert existing numbers to float:
>>> [converter(x) for x in ('1.1', 2, 'na')]
[1.1, 2.0, None]
When python lists, sets, dicts, etc are printed out, they are printed in the same format that python uses to compile the "raw code." Python compiles lists in quotes. So you just need to iterate over the list.
Simply use a generator expression to fix this (though it really doens't have much effect unless you are displaying on a tkinter widget or something):
>>> alist = ['4', '1.6', 'na', '2e-6', '42']
>>> for a in alist:
... print(a)
>>> 4
>>> 1.6
>>> na
>>> 2e-6
>>> 42
I'm not sure where the "na", "nan" confusion is coming from. Regardless, if you want to lose the quotes, run your code through a generator expression and it will no longer be under the "list class" - hence, the quotes will no longer appear.
The list elements are all still the same type,
edit: clarity, grammar
Related
I have a list of items stored in a list as a list of the list. I want to remove a particular character from each item if it is found. I am able to do it if I just use the first element of the list. However, I get "IndexError: list index out of range" while using for loop.
This is my list.
list1 = [['2.6x3.65'],[],['2','2.9x1.7','2.5x1.3']]
This is how I do for the first element.
if('x' in list1[0][0]):
rep1 = re.sub('x', ', ', list1[0][0])
This gives me the output as 2.6, 3.65 in string format which I can later convert to float.
However, when I implement the same using for loop using the following code:
for i in list1[i][i]:
if('x' in list1[i][i]):
rep2 = re.sub('x', ', ', list1[i][i])
It gives "IndexError: list index out of range" while using for loop.
My expected result is to get like the following:
list2 = [[2.6, 3.65],[],[2, 2.9, 1.7, 2.5, 1.3]]
You can use nested list comprehension:
list1 = [['2.6x3.65'], [], ['2', '2.9x1.7', '2.5x1.3']]
list2 = [sum([list(map(float, i.split('x'))) for i in l], []) for l in list1]
Output:
[[2.6, 3.65], [], [2.0, 2.9, 1.7, 2.5, 1.3]]
To not mix map() with list comprehension:
list2 = [[float(e) for i in l for e in i.split('x')] for l in list1]
Your code is likely getting the error because of this line:
for i in list1[i][i]:
...
It is not clear what the value of i is when evaluating list[i][i], but it would not work regardless, because what you would like to do is looping through your main list and also within each of its elements, which are also lists.
While you could figure this out with explicit indexing, Python offers you a better approach, namely looping through the elements directly.
Most importantly, in general, your regular expression approach would not be working because:
re.sub('x', ', ', list1[0][0])
is actually producing a string, which when printed, looks identical to the way Python would print a list of numbers, but it is not a list of numbers!
What you want to do instead is to convert your string to a numeric type.
If all you need is a list of floats, then just casting a valid text representation of a float would do the trick e.g. float('1.5') == 1.5. The same would hold for int, e.g. int('432') == 432 (but int('1.5') will raise a ValueError).
If you want to have different objects for ints and floats, as your expected output indicates, you could just first try to convert to int and if that fails, convert to float:
def to_number(value):
try:
value = int(value)
except ValueError:
value = float(value)
finally:
return value
With this in mind, you now need to make sure that the input of that function is going to be a string with a number.
Obviously, 1x2 or even 1, 2 are not, i.e. both int('1x2') and int('1, 2') (or with float instead of int) would rise a ValueError.
However, Python offers a simple way of parsing (well, splitting) that string in such a way that you would get '1' and '2' in a list:
'1x2'.split('x') == ['1', '2']
This also has the rather benign behavior of gracefully producing a consistent output even if you apply this to a text not containing the char to split, e.g.:
'1'.split('x') == ['1']
With all this building blocks, it is now possible to craft a sensible solution (making heavy use of list comprehensions):
list2 = [
[to_number(x) for elem in inner_list for x in elem.split('x')]
for inner_list in list1]
print(list2)
# [[2.6, 3.65], [], [2, 2.9, 1.7, 2.5, 1.3]]
(EDIT: added a number of explanations and wrote the code fully as list comprehensions).
This is one approach using ast and itertools.chain.
Ex:
from itertools import chain
import ast
list1 = [['2.6x3.65'],[],['2','2.9x1.7','2.5x1.3']]
result = []
for i in list1:
temp = []
for j in i:
temp.append(map(ast.literal_eval, j.split("x")))
result.append(list(chain.from_iterable(temp)))
print(result)
Output:
[[2.6, 3.65], [], [2, 2.9, 1.7, 2.5, 1.3]]
One approach would be to loop over your list and append to a new one:
list1 = [['2.6x3.65'],[],['2','2.9x1.7','2.5x1.3']]
new_l = []
for l in list1:
temp = []
for elem in l:
new_s = elem.split("x")
temp.extend([float(x) for x in new_s])
new_l.append(temp)
print(new_l)
# [[2.6, 3.65], [], [2.0, 2.9, 1.7, 2.5, 1.3]]
I'm new here so forgive me if there's anything unusual
I know it's simple to remove some whitespaces
but actually I'm not using strings, it's float elements list
so I'm using append to put the numbers in the list but they are passed in like this:
[1.2, 3.5, 41.2, 2.9]
I want them to be like this:
[1.2,3.5,41.2,2.9]
any kind of help will appreciated
There is no actual whitespace in the list. It is just how it's __str__ function is coded (the way it prints out). If you want to print it out without any spaces the best way to do it is convert it to a string first:
>>> test = [2, 32, 123, 1]
>>> test
[2, 32, 123, 1]
>>> print(str(test).replace(" ",""))
[2,32,123,1]
Both those list representations are equal, regardless of the whitespace added after the commas. The extra whitespace just makes it clearer to read.
To really test if they are equal, you can use == comparison:
>>> l1 = [1.2, 3.5, 41.2, 2.9]
>>> l2 = [1.2,3.5,41.2,2.9]
>>> l1 == l2
True
If you want a string representation without whitespace, you can use str.join():
>>> l1 = [1.2, 3.5, 41.2, 2.9]
>>> '[%s]' % ','.join(map(str, l1))
'[1.2,3.5,41.2,2.9]'
That is the default behavior of Python's __str__ but hey its Python and you can override the default behavior. I will not recommend to change the default code of __str__ but instead write your own list like class of yours to meet the requirement of yours
class my_list(list):
x=[]
def __init__(self, argument):
self.x=list(argument)
def __str__(self):
return '['+','.join(map(str,self.x))+']'
For testing
print(my_list([1.2, 3.5, 41.2, 2.9])) #[1.2,3.5,41.2,2.9,5,6]
This question already has answers here:
Apply function to each element of a list
(4 answers)
Closed 8 months ago.
The community reviewed whether to reopen this question 17 days ago and left it closed:
Original close reason(s) were not resolved
I need to join a list of items. Many of the items in the list are integer values returned from a function; i.e.,
myList.append(munfunc())
How should I convert the returned result to a string in order to join it with the list?
Do I need to do the following for every integer value:
myList.append(str(myfunc()))
Is there a more Pythonic way to solve casting problems?
Calling str(...) is the Pythonic way to convert something to a string.
You might want to consider why you want a list of strings. You could instead keep it as a list of integers and only convert the integers to strings when you need to display them. For example, if you have a list of integers then you can convert them one by one in a for-loop and join them with ,:
print(','.join(str(x) for x in list_of_ints))
There's nothing wrong with passing integers to str. One reason you might not do this is that myList is really supposed to be a list of integers e.g. it would be reasonable to sum the values in the list. In that case, do not pass your ints to str before appending them to myList. If you end up not converting to strings before appending, you can construct one big string by doing something like
', '.join(map(str, myList))
The map function in python can be used. It takes two arguments. The first argument is the function which has to be used for each element of the list. The second argument is the iterable.
a = [1, 2, 3]
map(str, a)
['1', '2', '3']
After converting the list into a string you can use the simple join function to combine the list into a single string
a = map(str, a)
''.join(a)
'123'
There are three ways of doing this.
let say you have a list of integers
my_list = [100,200,300]
"-".join(str(n) for n in my_list)
"-".join([str(n) for n in my_list])
"-".join(map(str, my_list))
However as stated in the example of timeit on python website at https://docs.python.org/2/library/timeit.html using a map is faster. So I would recommend you using "-".join(map(str, my_list))
a=[1,2,3]
b=[str(x) for x in a]
print b
above method is the easiest and most general way to convert list into string. another short method is-
a=[1,2,3]
b=map(str,a)
print b
Your problem is rather clear. Perhaps you're looking for extend, to add all elements of another list to an existing list:
>>> x = [1,2]
>>> x.extend([3,4,5])
>>> x
[1, 2, 3, 4, 5]
If you want to convert integers to strings, use str() or string interpolation, possibly combined with a list comprehension, i.e.
>>> x = ['1', '2']
>>> x.extend([str(i) for i in range(3, 6)])
>>> x
['1', '2', '3', '4', '5']
All of this is considered pythonic (ok, a generator expression is even more pythonic but let's stay simple and on topic)
For example:
lst_points = [[313, 262, 470, 482], [551, 254, 697, 449]]
lst_s_points = [" ".join(map(str, lst)) for lst in lst_points]
print lst_s_points
# ['313 262 470 482', '551 254 697 449']
As to me, I want to add a str before each str list:
# here o means class, other four points means coordinate
print ['0 ' + " ".join(map(str, lst)) for lst in lst_points]
# ['0 313 262 470 482', '0 551 254 697 449']
Or single list:
lst = [313, 262, 470, 482]
lst_str = [str(i) for i in lst]
print lst_str, ", ".join(lst_str)
# ['313', '262', '470', '482'], 313, 262, 470, 482
lst_str = map(str, lst)
print lst_str, ", ".join(lst_str)
# ['313', '262', '470', '482'], 313, 262, 470, 482
Maybe you do not need numbers as strings, just do:
functaulu = [munfunc(arg) for arg in range(loppu)]
Later if you need it as string you can do it with string or with format string:
print "Vastaus5 = %s" % functaulu[5]
How come no-one seems to like repr?
python 3.7.2:
>>> int_list = [1, 2, 3, 4, 5]
>>> print(repr(int_list))
[1, 2, 3, 4, 5]
>>>
Take care though, it's an explicit representation. An example shows:
#Print repr(object) backwards
>>> print(repr(int_list)[::-1])
]5 ,4 ,3 ,2 ,1[
>>>
more info at pydocs-repr
I can't imagine I'm going to get much help from this due to my inability to explain it. But for instance I have a string like so:
s = "[1,[2,2,[3,4]],5]"
and I need to convert it into a nested list item as such
lst = ["1",["2","2",["3","4"]],"5"]
that if I were to go lst[1][2][0] it would return '3'.
The way I have tried to do it was by creating a substring for every number within '[' and end of string characters and then slowly nest it back up
def ParseList(strlist):
if '[' in strlist:
print strlist
return ParseList(GetBetweenChar(strlist,'[',None))
else:
return strlist
however it returns:(which although maybe a good start? I dont know where to continue)
[1,[2,2,[3,4]],5]
1,[2,2,[3,4]],5
2,2,[3,4]],
3,4]]
which I would think I would append that to a list item but I dont know how to..
You can use ast.literal_eval to safely convert the string to a nested list of integers. Then define a nested map function to convert to all elements to strings, whilst maintaining the nesting structure.
from ast import literal_eval
s = "[1,[2,2,[3,4]],5]"
ls = literal_eval(s)
# yes I know there is something else called nmap
def nmap(fn, iterable):
res = []
for i in iterable:
if isinstance(i, list): # could be tuple or something else?
res.append(nmap(fn, i))
else:
res.append(fn(i))
return res
result = nmap(str, ls)
print(result)
print(result[1][2][0])
result:
['1', ['2', '2', ['3', '4']], '5']
3
You can use eval(). Just be careful to make sure the string is safe because eval will convert a string to valid python code.
>>> eval("[1,[2,2,[3,4]],5]")[1][2][0]
3
Some more info: What does Python's eval() do?
If you didn't require every piece to be a string, but you could let numbers be numbers, then you can use the json library:
>>> s = "[1,[2,2,[3,4]],5]"
>>> import json
>>> json.loads(s)
[1, [2, 2, [3, 4]], 5]
Notice that if your original list contains numbers or booleans, they will stay as numbers or booleans. This is probably what you want, BUT if you really need everything to be strings, then you can recurse through the nested arrays and apply str to everything (look for "How to do flatmap in Python") or request further help in the comment section below.
You could proceed by first adding the quotes around the digits, then eval the list:
s = "[1,[2,2,[3,4]],5]"
res = ''
for c in s:
if c.isdigit():
res += '"' + c + '"'
else:
res += c
s = eval(res)
s
output:
['1', ['2', '2', ['3', '4']], '5']
This will work for single digit numbers; a little bit more work would be needed for multiple digits, or floats
Eval is not safe for user input.
You can do something like for python (2.6+):
>>> import ast
>>> s = "[1,[2,2,[3,4]],5]"
>>> lst = ast.literal_eval(s)
>>> str(lst[1][2][0])
'3'
Actually quite simple question:
I've a python list like:
['1','2','3','4']
Just wondering how can I strip those single quotes?
I want [1,2,3,4]
Currently all of the values in your list are strings, and you want them to integers, here are the two most straightforward ways to do this:
map(int, your_list)
and
[int(value) for value in your_list]
See the documentation on map() and list comprehensions for more info.
If you want to leave the items in your list as strings but display them without the single quotes, you can use the following:
print('[' + ', '.join(your_list) + ']')
If that's an actual python list, and you want ints instead of strings, you can just:
map(int, ['1','2','3','4'])
or
[int(x) for x in ['1','2','3','4']]
Try this
[int(x) for x in ['1','2','3','4']]
[1, 2, 3, 4]
and to play safe you may try
[int(x) if type(x) is str else None for x in ['1','2','3','4']]