0

I was wondering how do you mix list and dict together on Python? I know on PHP, I can do something like this:

$options = array(
    "option1", 
    "option2", 
    "option3" => array("meta1", "meta2", "meta3"), 
    "option4" 
);

The problem is python have different bracket for different list. () for tuple, [] for list, and {} for dict. There don't seems to be any way to mix them and I'm keep getting syntax errors.

I am using python 2.7 now. Please advice how to do it correctly.

Much thanks,

Rufas

Update 1:

I'll slightly elaborate what I'm trying to do. I am trying to write a simple python script to do some API requests here:

http://www.diffbot.com/products/automatic/article/

The relevant part is the fields query parameters. It is something like ...&fields=meta,querystring,images(url,caption)... . So the above array can be written as (in PHP)

$fields = array(
    'meta',
    'querystring',
    'images' => array('url', 'caption')
);

And the $fields will be passed to a method for processing. The result will be returned, like this:

$json = diffbot->get("article", $url, $fields);

The thing is - I have no problem in writing it in PHP, but when I try to write it in Python, the thing is not as easy as it seems...

Rufas Wan
  • 43
  • 1
  • 7
  • Something like this? `x = ['first', 'second', {'third':['blah']}]` –  Jan 02 '14 at 17:15
  • it is something like this: x = ['first', 'second', 'third':['blah','blah'], 'forth'] . Been trying to replace the brackets with {} here and there to make the code work, but it doesn't. – Rufas Wan Jan 02 '14 at 17:30

3 Answers3

4

You can do it this way:

options = {
    "option1": None, 
    "option2": None,
    "option3": ["meta1", "meta2", "meta3"], 
    "option4": None,
}

But options is a dictionary in this case. If you need the order in the dictionary you can use OrderedDict.

How can you use OrderedDict?

from collections import OrderedDict

options = OrderedDict([
    ("option1", None),
    ("option2", None),
    ("option3", ["meta1", "meta2", "meta3"]), 
    ("option4", None),
])

print options["option3"]
print options.items()[2][1]
print options.items()[3][1]

Output:

['meta1', 'meta2', 'meta3']
['meta1', 'meta2', 'meta3']
None

Here you can access options either using keys (like option3), or indexes (like 2 and 3).

Disclaimer. I must stress that this solution is not one-to-one mapping between PHP and Python. PHP is another language, with other data structures/other semantics etc. You can't do one to one mapping between data structures of Python and PHP. Please also consider the answer of Hyperboreus (I gave +1 to him). It show another way to mix lists and dictionaries in Python. Please also read our discussion below.

Update1.

How can you process such structures?

You must check which type a value in each case has. If it is a list (type(v) == type([])) you can join it; otherwise you can use it as it is.

Here I convert the structure to a URL-like string:

options = {
    "option1": None,
    "option2": None,
    "option3": ["meta1", "meta2", "meta3"], 
    "option4": "str1",
}

res = []
for (k,v) in options.items():
    if v is None:
        continue
    if type(v) == type([]):
        res.append("%s=%s" % (k,"+".join(v)))
    else:
        res.append("%s=%s" % (k,v))

print "&".join(res)

Output:

option4=str1&option3=meta1+meta2+meta3
Igor Chubin
  • 61,765
  • 13
  • 122
  • 144
  • @Hyperboreus: Please see my note about `OrderedDict` – Igor Chubin Jan 02 '14 at 17:17
  • Alternatively one can use the empty list `[]` instead of `None` to denote no elements. Then all values have the same type and can be passed to the same functions. (sort of). – Andreas Vinter-Hviid Jan 02 '14 at 17:21
  • @IgorChubin Still you are mixing up keys and values. Php arrays are ordered maps. According to the documentation, when an element of an array declaration omits the `=>` it is taken as a value and its keys is the next unused integer. So I fail to see how your answer relates to the question. – Hyperboreus Jan 02 '14 at 17:25
  • @IgorChubin Thanks for providing negative proof. `options.items()[2][1]` gives `['meta1', 'meta2', 'meta3']`. In php `$options[2][1]` gives `"p"`. – Hyperboreus Jan 02 '14 at 17:30
  • @Hyperboreus: The question was "how you can mix list and dict together on Python?" I don't say that it exactly the same as it is in PHP. – Igor Chubin Jan 02 '14 at 17:31
  • options order is not important, and all options is optional. It can be a string, it can be a list. When it is a list, I'll need to process and convert it into string, like "option3": ["meta1", "meta2", "meta3"] becomes "option3=meta1+meta2+meta3" to continue – Rufas Wan Jan 02 '14 at 17:37
1

This seems to do the same thing:

options = {0: 'option1',
    1: 'option2',
    2: 'option4'
    'option3': ['meta1', 'meta2', 'meta3'] }

More in general:

[] denote lists, i.e. ordered collections: [1, 2, 3] or [x ** 2 for x in [1, 2, 3]]

{} denote sets, i.e. unordered collections of unique (hashable) elements, and dictionaries, i.e. mappings between unique (hashable) keys and values: {1, 2, 3}, {'a': 1, 'b': 2}, {x: x ** 2 for x in [1, 2, 3]}

() denote (among other things) tuples, i.e. immutable ordered collections: (1, 2, 3)

() also denote generators: (x ** 2 for x in (1, 2, 3))

You can mix them any way you like (as long as elements of a set and keys of a dictionary are hashable):

>>> a = {(1,2): [2,2], 2: {1: 2}}
>>> a
{(1, 2): [2, 2], 2: {1: 2}}
>>> a[1,2]
[2, 2]
>>> a[1,2][0]
2
>>> a[2]
{1: 2}
>>> a[2][1]
2
Hyperboreus
  • 31,997
  • 9
  • 47
  • 87
  • in this case `options[0]=='option1'`, `options[1]=='option2'`, `options[2]=='option4'`, but `options[3]==KeyError: 3` – Adam Smith Jan 02 '14 at 17:32
  • @adsmith Also in PHP `$options` does not contain key `3`. Only that php handles unknown keys differently. – Hyperboreus Jan 02 '14 at 17:32
  • 1
    @Hyperboreus but he's not programming in PHP so I don't see how that's relevant. OPs example seems to be how to put a list in a list, and this is clearly not how to do it. `options = ['option1','option2',['meta1','meta2','meta3'],'option4']` is a much cleaner data structure. Don't do things how PHP does it just because that's how PHP does it -- make it better. – Adam Smith Jan 02 '14 at 17:40
0

I'm pretty sure there are 3 answers for my question and while it received a -1 vote, it is the closest to what I want. It is very strange now that it is gone when I want to pick that one up as "accepted answer" :(

To recap, the removed answer suggest I should do this:

options = [
    "option1", 
    "option2", 
    {"option3":["meta1", "meta2", "meta3"]}, 
    "option4" 
]

And that fits nicely how I want to process each item on the list. I just loop through all values and check for its type. If it is a string, process it like normal. But when it is a dict/list, it will be handled differently.

Ultimately, I managed to make it work and I get what I want.

Special thanks to Igor Chubin and Hyperboreus for providing suggestions and ideas for me to test and discover the answer I've been looking for. Greatly appreciated.

Thank you!

Rufas

Rufas Wan
  • 43
  • 1
  • 7