Concatenate items into a vector

Asked

Viewed 240 times

0

I have the following vector, which I obtain after consulting a database:

a = ['[[10, 20], 10]']

When I try to access their values through the indexes, I can’t.

For example, if you type: print(a[0][0]). Is Returned '['

I’ve tried to do: b = ''.join(a) print. However, this situation continues.

I need this vector to be converted "really" into a vector.

For example, if I want to check the value [10, 20], i do print(a[0]). If you want to consult 20, print(a[0][1])

I have tried many solutions (with Join, numpy and etc...). Someone could help me?

  • But what you’re getting from the bank is a string, not a list. The object a is a list with only one value, of the type string.

  • Yes. You’re right! There is some way to fix this. I ask, why don’t I really know @Andersoncarloswoss.

  • Danilo, what do these values represent? Why are they stored like this in the table?

2 answers

3

The return you get from the database is a string that represents the syntax of a Python list, not a list itself. To use it as a list, you need Python to interpret the chunk of code it represents, and to do this there are some options.


Ast.literal_eval()

Whereas the string contains Python code and is a literal structure (string, number, tuple, list, dict, boolean or None), you can use the function ast.literal_eval(). The library ast enables the programmatic interpretation of the Python syntax, so that the function in question receives a literal structure string and returns it interpreted at runtime:

>>> import ast
>>> retorno = '[[10, 20], 10]'
>>> a = ast.literal_eval(retorno)
>>> print(a[0][0])
10
>>> print(a[0][1])
20

(exemlo no repl.it: https://repl.it/M4fP/1)


json.loads()

Since your string example for parse also represents a JSON array, you can use the Python JSON parser to interpret it safely, as shown by @Anderson-carlos-woss in the accepted answer:

>>> import json
>>> retorno = '[[10, 20], 10]'
>>> a = json.loads(retorno)
>>> print(a[0][0])
10
>>> print(a[0][1])
20

(example in repl.it: https://repl.it/M4fP/2)


yaml.safe_load

Parsers from other serialization languages that use array representation equal to JSON, such as YAML (actually JSON is a "subgroup" of YAML), may also be useful to you. YAML particularly has a function safe_load():

>>> import yaml
>>> retorno = '[[10, 20], 10]'
>>> a = yaml.safe_load(retorno)
>>> print(a[0][0])
10
>>> print(a[0][1])
20

(example in repl.it: https://repl.it/M4fP/3)

More about YAML parser and secure data entry in Python programs: Openstack: Avoid Dangerous file Parsing and Object serialization Libraries


Eval() (high security risk)

The option less secure is the use of the function eval(). It takes a Python code string and executes it:

>>> retorno = '[[10, 20], 10]'
>>> a = eval(retorno)
>>> print(a[0][0])
10
>>> print(a[0][1])
20

(example in repl.it: https://repl.it/M4fP/0)

The lack of security is due to the fact that the function eval() execute each and every code past. Therefore, the results can be catastrophic if some malicious user is able to change their database data to that variable retorno contain any unwanted commands. As a rule, do not use eval() even if you trust the string, because you never know how it can be intercepted by someone.


For more information about the danger of using eval():

Stack Overflow: Eval is either a bad guy or a bad guy?

Ned Batchelder: Eval really is Dangerous

Kevin London: Dangerous Python Functions, Part 1

  • Why downvote? Did I say something silly? The example above works on the Python console.

  • Thank you @nunks.lol!

  • 1

    (the downvote is not mine), but it must be because "Eval" is not something to use light-hearted, being an instruction with very serious security problems - in addition to performance problems. If the string contains a Python expression, it is best to use import ast; ast.liteteral_eval - which only converts literal values: if someone places strings with function calls or python expressions in the database. they will not be executed. Another option, in this case, is to use the JSON parser for the column - even more relaxed than the ast.literal_eval.

  • 1

    For example, if someone puts this string here in your database and has an Eval: __import__("os").system("rm -rf /") - was already.

  • 1

    (My concern is not that you put Val - everybody’s here to learn. My concern is just the upvotes for your answer - but switch to Ast.literal_eval, and add some link to the dangers of pure Val, that this response becomes a very legal contribution to S.O.)

  • 1

    @jsbueno I understand the risks of using Val, I just thought of the simplest solution, without import, and I didn’t realize that it could be something so harmful in a response because of the credibility inherent in upvotes. I fully agree with that position and will better elaborate the response to serve as a warning as to the use of Eval. Thank you! =)

Show 1 more comment

3


What you are receiving from the database seems to be a list of only one value string, then you will not be able to access the values as if it were a list. What you can do, and it works for this specific case, is to convert your string to a list via a JSON analysis:

import json

a = ['[[10, 20], 10]']

lista = json.loads(a[0])

print(lista[0])    # [10, 20]
print(lista[0][1]) # 20

But if this is coming from the database, there are serious indications that your tables are poorly structured.

  • Thank you. @Anderson Carlos Woss! I will review the table. However, the table is for personal use, very simple. But, I appreciate the comment. If it were a commercial application, it would be modified for sure!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.