3

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..

1
  • sorry my fault I implied the input would only be integers rather it has to be able to feature strings,characters,booleans and integers for example: lst = ["x",["2","2",["True","4"]],"5"] Commented Oct 31, 2017 at 4:02

5 Answers 5

2

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

Sign up to request clarification or add additional context in comments.

9 Comments

Okay. This works for numbers, but to be fair I wasent upfront with what input will be passing through, the integers as the input were just a test instead all means of data types will be put in such as strings,booleans and integers. which returns a malformed string error. How can I allow this to also accept other data types?
Can you add an example to your question, so I can try to reproduce the error myself?
How do you mean by example? like a use case or? I just commented on my own question what the input could look like if thats what you mean. :)
Are you sure? why not "['x',[2,2,[True,4]],5]" (the x value is quoted). Without the quotes, it would interpret x as a variable called x and would complicate the requirements to parse it.
If you can add the quotes it means a solution like I have here, could work. If not then you'll have to do the parsing yourself. You'd have to split the string on brackets and commas and try the different possible conversions and if int or bool failed you could fall back on string. It's not entirely trivial and is introduces some ambiguities (e.g. is True the boolean True or the string "True"). Perhaps I'm over complicating it, but it seems to be a lot harder without the quotes.
|
0

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?

1 Comment

This produces an int. The requirements was to produce a string.
0

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.

2 Comments

This also works just fine but only (as I said in my other comment by Paul) works with the integers, if I were to add a string or character into the list it returns ValueError: No JSON object could be decoded
Well that error would only occur if you single-quoted the strings. If the strings inside were double quoted, such as '["abc", 1]' then it would work. Can I ask whether your expected input will have quoted strings, or will the tokens be unquoted? And what about commas? Can the values themselves have commas? Getting this exactly right can be very tricky, but if you can fully specify expected inputs and outputs I would be happy to help
0

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

Comments

0

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'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.