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]
Related
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
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'
What is the cleanest way to obtain a list of the numeric values in a string?
For example:
string = 'version_4.11.2-2-1.4'
array = [4, 11, 2, 2, 1, 4]
As you might understand, I need to compare versions.
By "cleanest", I mean as simple / short / readable as possible.
Also, if possible, then I prefer built-in functions over regexp (import re).
This is what I've got so far, but I feel that it is rather clumsy:
array = [int(n) for n in ''.join(c if c.isdigit() else ' ' for c in string).split()]
Strangely enough, I have not been able to find an answer on SO:
In this question, the input numeric values are assumed to be separated by white spaces
In this question, the input numeric values are assumed to be separated by white spaces
In this question, the user only asks for a single numeric value at the beginning of the string
In this question, the user only asks for a single numeric value of all the digits concatenated
Thanks
Just match on consecutive digits:
map(int, re.findall(r'\d+', versionstring))
It doesn't matter what's between the digits; \d+ matches as many digits as can be found in a row. This gives you the desired output in Python 2:
>>> import re
>>> versionstring = 'version_4.11.2-2-1.4'
>>> map(int, re.findall(r'\d+', versionstring))
[4, 11, 2, 2, 1, 4]
If you are using Python 3, map() gives you an iterable map object, so either call list() on that or use a list comprehension:
[int(d) for d in re.findall(r'\d+', versionstring)]
I'd solve this with a regular expression, too.
I prefer re.finditer over re.findall for this task. re.findall returns a list, re.finditer returns an iterator, so with this solution you won't create a temporary list of strings:
>>> [int(x.group()) for x in re.finditer('\d+', string)]
[4, 11, 2, 2, 1, 4]
You are tracking every character and checking if it is a digit, if yes you are adding it to a list, Gets slow for larger strings.
Let's say,
import re
string='version_4.11.2-2-1.4.9.7.5.43.2.57.9.5.3.46.8.5'
l=map(int, re.findall('\d+',string))
print l
Hopefully, this should work.
Not sure in the answer above why are we using 'r'.
You can simply resolve this using regular expressions.
import re
string = 'version_4.11.2-2-1.4'
p=re.compile(r'\d+')
p.findall(string)
Regex is definitely the best way to go as #MartijnPieters answer clearly shows, but if you don't want to use it, you probably can't use a list comprehension. This is how you could do it, though:
def getnumbers(string):
numberlist = []
substring = ""
for char in string:
if char.isdigit():
substring += char
elif substring:
numberlist.append(int(substring))
substring = ""
if substring:
numberlist.append(int(substring))
return numberlist
Lists already have an insert() method that works with indexes:
>>> someList = [1, 2, 4, 5]
>>> someList
[1, 2, 4, 5]
>>> someList.insert(2, 3)
>>> someList
[1, 2, 3, 4, 5]
If strings also have indexes, why not an insert() method for them too? Example below:
>>> someString = 'foobar'
>>> someString.insert(3, 'SPAM')
>>> someString
'fooSPAMbar'
Short answer: Because strings are immutable.
Every type in Python is either mutable (like a list, a dictionary, or a normal object) , or immutable (like tuples, strings, ints, ...).
That's why you can append, pop, and insert in and from lists, but not tuples.
When you do something like this:
a = "this"
a = a + "that"
a seems to have "changed" to "thisthat", but actually, the name a just points to a new string. You can observe that effect if you hand something to a function and try to modify it in the function: Mutable types will also change outside (although you should usually avoid these side-effects), while immutables won't:
a = 3
b = [3]
def change_a(something):
something = 4
def change_b(something):
something[0] = 4
change_a(a)
change_b(b)
print(a,b) # prints "3 4"
If you need to mutate strings, you might want to look into StringIO for Python 2, or io.StringIO for Python 3, respectively:
import io
def insert(s,where,what):
whatlen=len(what)
s.seek(0)
cur=len(s.read())
if cur < where:
raise IndexError("Can't insert at position {}: Index out of bounds"
.format(where))
s.seek(where)
r=s.read()
s.seek(where+whatlen)
s.write(r)
s.seek(where)
s.write(what)
s = io.StringIO("This is a test")
insert(s,5,"hello")
s.seek(0)
print(s.read()) #prints "This hellois a test"
Because strings are immutable. You can't change the contents of a string. You'd have to make a new string.
Because strings are decidedly immutable. As are tuples.
Traditional strings are immutable. You can actually use the deprecated MutableString to do this:
string = UserString.MutableString('foobar') # then insert, call string.insert(3, 'SPAM')
Hence List are a mutable we can make changes in a list. But Strings ar ean immutable one, we can append charaters in a string. But we cannot change the index position values in a string.
Suppose I want to change 'abc' to 'bac' in Python. What would be the best way to do it?
I am thinking of the following
tmp = list('abc')
tmp[0],tmp[1] = tmp[1],tmp[0]
result = ''.join(tmp)
You are never editing a string "in place", strings are immutable.
You could do it with a list but that is wasting code and memory.
Why not just do:
x = 'abc'
result = x[1] + x[0] + x[2:]
or (personal fav)
import re
re.sub('(.)(.)', r'\2\1','abc')
This might be cheating, but if you really want to edit in place, and are using 2.6 or older, then use MutableString(this was deprecated in 3.0).
from UserString import MutableString
x = MutableString('abc')
x[1], x[0] = x[0], x[1]
>>>>'bac'
With that being said, solutions are generally not as simple as 'abc' = 'bac' You might want to give us more details on how you need to split up your string. Is it always just swapping first digits?
You cannot modify strings in place, they are immutable. If you want to modify a list in place, you can do it like in your example, or you could use slice assignment if the elements you want to replace can be accessed with a slice:
tmp = list('abc')
tmp[0:2] = tmp[1::-1] # replace tmp[0:2] with tmp[1::-1], which is ['b', 'a']
result = ''.join(tmp)