0

I have a string, which is a 2d array, with the following fields [fruitname,qty,date,time]

Sample list:

['apples',1,'04-07-2022','16:35'],['oranges',5,'04-07-2022','18:35'],['mangoes',10,'04-07-2022','16:00']

I would like to store the above in a list in python (fruitsPurchaseList) and access it.

For example, if I wanted to get the quantity of mangoes purchased, I'd access it by something like:

mangoQty = fruitsPurchaseList[2][1]

EDIT:

The list also has some blanks.

Sample list:

['apples',1,'04-07-2022','16:35'],['oranges',5,'04-07-2022','18:35'],['mangoes',10,'04-07-2022','16:00'],['bananas',,'04-09-2022','11:00']

cruzerkk
  • 17
  • 1
  • 2
  • 6
  • @oda How can I convert a string that is in 2d form to a python list that is in 2d form – cruzerkk Apr 12 '22 at 02:16
  • I believe that it does not like the fact that some of the fields are blank in my actual 2d list. It gives me an error: invalid syntax (, line 43). How do I account for something like ['mangoes',,'04-07-2022','16:00'], is the error expected? If so, how do I supress/make it ignore those ? – cruzerkk Apr 12 '22 at 02:46
  • Unfortunately not, but my edit is similar to the actual list structure. Your solution works until a blank is encountered as shown for "bananas" in the Edit – cruzerkk Apr 12 '22 at 02:51
  • Okay. I will see what I can do! – OTheDev Apr 12 '22 at 02:52
  • See my updated answer. Does that help? – OTheDev Apr 12 '22 at 02:56
  • That worked ! Thanks a ton. I don't know why would someone downvote the answer. I tried to upvote it, but unfortunately don't have enough reputation to do so. But thanks a lot! – cruzerkk Apr 12 '22 at 03:00
  • Glad to hear that it works! Btw, I extended my answer a tiny bit just in case you encounter empty fields that potentially have spaces between the commas. That approach is more general and actually is probably preferred over the original approach. My answer includes this better approach. – OTheDev Apr 12 '22 at 03:09
  • Hi @cruzerkk, just want to clarify. isn't your list of string already a python list? –  Apr 12 '22 at 05:17

2 Answers2

-1

EDIT: original version used eval; new version uses literal_eval from the standard ast module.

If you have a string that represents a list of lists and want to turn that into a list,

  1. you can use the built-in Python function eval() (documentation). eval() accepts a string as an argument and evaluates it as a Python expression (after parsing the string). The result of the evaluated expression is returned. If you do use eval, you must be sure that the input source to eval is trusted.
  2. you should (see discussion at end of post) use the function literal_eval (documentation) from the ast module from the Python Standard Library.

This code does what you want using literal_eval (eval achieves the same effect but see note below).

from pprint import pprint
from ast import literal_eval
# import re 

s = """
[
['apples',1,'04-07-2022','16:35'],
['oranges',5,'04-07-2022','18:35'],
['mangoes',10,'04-07-2022','16:00'],
['bananas',,'04-09-2022','11:00']
]
"""

s = s.replace(",,", ",'',")
# s = re.sub(r', *,', ",'',", s) 

l = literal_eval(s)
pprint(l)
print(f"\nMango Quantity: {l[2][1]}")

The above replaces all occurrences of ',,' with ",'',". If in the empty fields there are an arbitrary number of spaces between the commas (but nothing else), remove the s.replace line and uncomment the two commented-out lines. Using re.sub is a more general solution.

Output

[['apples', 1, '04-07-2022', '16:35'],
 ['oranges', 5, '04-07-2022', '18:35'],
 ['mangoes', 10, '04-07-2022', '16:00'],
 ['bananas', '', '04-09-2022', '11:00']]

Mango Quantity: 10

Safety Note


In many contexts, eval and literal_eval will achieve the same effect, as in this example. However, eval is known to be potentially very dangerous. eval takes its string argument, parses it and evaluates it as a Python expression. This can be an arbitrary Python expression. One concern is that Python permits users to access and delete system files (e.g. via the os module). So a bad-actor may supply dangerous data that you feed into eval, which could corrupt your system. This is why you need to be extra careful that you can trust the input source before supplying it to eval. literal_eval also accepts a string as an argument, but this is restricted to only contain (quote from literal_eval doc cited above)

Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, None and Ellipsis. This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions[.]

In your case, you know that your string data represents a nested list that should only have numbers and strings as elements. So to be safe, use literal_eval, which would not evaluate a non-allowed expression. So if your list had elements that would normally evaluate to something dangerous (which eval would evaluate), literal_eval would not evaluate it -- it is restricted to Python literal structures. In this case, even if you know and absolutely trust your input source, there is no harm in using literal_eval instead.

Be safe!

Hope this helps. Please let me know if there are questions/concerns!

OTheDev
  • 2,916
  • 2
  • 4
  • 20
  • 1
    This answer worked for me – cruzerkk Apr 12 '22 at 03:00
  • I didn't downvote, but I can venture a guess why you received two downvotes. You recommended using `eval` without even mentioning its dangers. – Stef Apr 12 '22 at 10:04
  • 1
    Note: in standard module `ast` there is a function `literal_eval` which in effect is a bit similar to `eval`, except it only evaluates literals (ie, no variable names, no function calls, no generators or list comprehensions, etc). It's a lot safer than eval, and works as well in this case. – Stef Apr 12 '22 at 10:10
  • Related: [Using python's eval() vs. ast.literal_eval()](https://stackoverflow.com/questions/15197673/using-pythons-eval-vs-ast-literal-eval) – Stef Apr 12 '22 at 10:17
  • Thanks anyways for letting me know! @Stef – OTheDev Apr 12 '22 at 10:22
  • @Stef I have updated my answer. Okay, you think? – OTheDev Apr 12 '22 at 11:16
  • @cruzerkk Just to let you know I have updated my answer. In terms of the code, the only difference is the use of `literal_eval` from the `ast` module instead of the built-in `eval`. In your case both achieve the same effect though `eval` can be dangerous if you cannot trust the input source. I have included a warning in my answer. `literal_eval` is recommended. – OTheDev Apr 12 '22 at 11:21
-2

You can use append() to add any element to a list in python - this includes other lists! Use a for loop to loop through each string element and append it to your new list. Access the elements as you showed in your example - listname[element index in whole list][element index in sublist].

string = ['apples',1,'04-07-2022','16:35'],['oranges',5,'04-07-2022','18:35'],['mangoes',10,'04-07-2022','16:00']
fruitsPurchaseList = []

for s in string:
    fruitsPurchaseList.append(s)

print(f"The fruits purchase list is: {fruitsPurchaseList}")

mangoQty = fruitsPurchaseList[2][1]

print(f"The mango quantity is: {mangoQty}")

Output is as follows:

The fruits purchase list is: $[['apples', 1, '04-07-2022', '16:35'], ['oranges', 5, '04-07-2022', '18:35'], ['mangoes', 10, '04-07-2022', '16:00']]
The mango quantity is: $10
Cassie
  • 16
  • 3