2

Python beginner question:

Is there a way to convert a string of the form '[a, b, c]' directly into a list?

As in type(f('[a, b, c]')) is list == True/isinstance(f('[a, b, c]'), list) is True for some method or function f? Please note, the final lists should have the elements as individual strings, i.e. f('[a, b, c]') returns ['a', 'b', 'c']

I have checked this and this. ast.literal_eval() Fails with error:

ValueError: malformed string

My input list (string) isn't unicode marked, and the items are not individually string or int.

Is there a builtin for this kind of conversion? This is essentially a 'form' question. I am trying to understand if there is a pythonic way of doing this without writing a longish function using splitting the string and conversion.

Insights would be much appreciated.

Community
  • 1
  • 1
  • No, there isn't a built-in for this - why doesn't your string have quotes around the list contents? Where do you get it from? – jonrsharpe Jul 02 '14 at 10:14
  • Why don't you want to use a list comprehension? – timgeb Jul 02 '14 at 10:15
  • How should it deal with `"[a, 1, b]"` - should it give `["a", "1", "b"]` or `["a", 1, "b"]`? Either way it is going to need a list comprehension or loop to parse the string because it is not a valid string representation of a list. – neil Jul 02 '14 at 10:22
  • also, how should it deal with nested lists? – timgeb Jul 02 '14 at 10:24
  • is your list will be always in this format ? – Freelancer Jul 02 '14 at 10:26
  • @jonrsharpe: I get it from a string of the shape [a, b, c]@abc.com. – Coriolis Force Jul 02 '14 at 11:14
  • @timegb: as I explained, it is a matter of form, I am trying to learn how to write it more pythonically, as in brevity and elegance. list comprehension is extrmely pythonic, I agree though. – Coriolis Force Jul 02 '14 at 11:15
  • @CoriolisForce, what happens for ints and sublists etc.. – Padraic Cunningham Jul 02 '14 at 11:18
  • @PadraicCunningham the source of this emits the strings in that particular format. Once I have the list, it will be further processed to extract strings in a a@abc.com, b@abc.com etc. we don't know how many strings there will be. – Coriolis Force Jul 02 '14 at 11:21
  • @CoriolisForce, my question is what happens with something like '[a, b, c,1, 2, 3,[3,4]]'? – Padraic Cunningham Jul 02 '14 at 11:23
  • @PadraicCunningham, in that case, this solution breaks, but honestly I didn't ask that in the question. Any insight would be most interesting though. Thanks. – Coriolis Force Jul 02 '14 at 11:30
  • Thanks all, I think this is a great discussion. I also think that the idea also is to make the code more generic than hard coded. Any insights will be well-appreciated. Taking from @PadraicCunningham's point, I think it'd be nice if we can generalize this code a bit, so that it can, if needed be, applied to nested phenomena. Thanks again. Also, I think any insights on this part of the question would be helpful: "I am trying to understand if there is a pythonic way of doing this without writing a longish function using splitting the string and conversion." – Coriolis Force Jul 02 '14 at 11:33

5 Answers5

2

Try this:

s = '[a ,b, c]'
s = s.replace(" ", "")
l = s[1:-1].split(',')
Freelancer
  • 4,459
  • 2
  • 22
  • 28
1

I know the OP explicitly asks for a non list comprehension solution, however just for those who might be interested in a solution involving list comprehension I leave this code:

>>> s = "[a, 1, b]"
>>> s = [int(i) if i.strip().isdigit() else i.strip() for i in s[1:-1].split(",")]
>>> print(s)
 ['a', 1, 'b']

It also takes into accounts the type of the elements, ints are converted to int.

jabaldonedo
  • 25,822
  • 8
  • 77
  • 77
  • The question title states "without going through list comprehension", if someone comes looking here for a solution using list comp I think they have some bigger problems ;) – Padraic Cunningham Jul 02 '14 at 11:11
0

Using literal_eval this keeps ints as ints and preserves sublists.

In [7]: import re

In [8]: d='[a, b, c, 4, 5, 6,[1,4]]'

In [9]: from ast import literal_eval

In [10]: lit = literal_eval(re.sub('([A-Za-z])', r'"\1"', d))

In [11]: lit[6]
Out[11]: [1, 4]

In [12]: type(lit[6])
Out[12]: list

In [13]: lit
Out[13]: ['a', 'b', 'c', 4, 5, 6, [1, 4]]

If you want to mix numbers and letters you would need to convert all the ints to strings also.

You can also add to the pattern to find strings including @ and .:

In [16]: d='[a, ba, c, 4, 5, 6,[1,4],me@you.com]'

In [17]: lit = literal_eval(re.sub('([A-Za-z@.])', r'"\1"', d))

In [18]: lit
Out[18]: ['a', 'ba', 'c', 4, 5, 6, [1, 4], 'me@you.com']
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
0

This should do it:

s = '[a, b, c]'
s = s[1:-1]
s = s.split(', ')

or as a one-liner:

s = s[1:-1].split(', ')
ncocacola
  • 485
  • 3
  • 9
  • If possible, can that `s[1:-1]` be replaced by something else? As I wrote above, makes it look a little hard-coded. – Coriolis Force Jul 02 '14 at 11:26
  • The only other alternative I know of would be `s = s.replace('[', '').replace(']', '')`, but I think `s[1:-1]` is better because it says 's excluding the first and last character of s', which is exactly what we want. It's standard Python AFAIK. – ncocacola Jul 02 '14 at 14:21
  • this will give s=["'a'","'b'","'c'"] – Miffy Mar 12 '19 at 06:25
0

yes, there is way for transforming string "[a,b,c]" directly into a list:

a="hello"
b=" "
c="world"

lststr = "[a,b,c]"

# now 'exec()' can be used for declaring a variable 
# and assigning string 'lststr' to it as a list variable

exec("lstvar = "+lststr)
Kalle
  • 11
  • 1