0

I have a python dictionary with several keys and I want each key to become a bidimensional array (list of list) like this:

mydict:{'key1':[['l1v1','l1v2'],['l2v1','l2v2']],'key2':[['l1v1','l1v2'],['l2v1','l2v2']]...}

The values I want to assign are chars forming a long string.

myStr = 'a_very_very_very_very_very_very_very_long_string.....'

What I'm doing is something like this:

 i = 0
 for gr in range(2):
     tmp = []
     for ch in range(2):
        tmp.append(myStr[i])
        i += 1
     mydict['key1'].append(tmp)

But I'm quite sure this isn't the most efficient/elegant/pythonic way of doing it and I'll have to use a temporal list for every key in my dictionary.

Do you have a suggestion for this? Thanks!

UPDATE

It seems like I made myself misunderstood so I'll give a more detailed explanation of what I'm trying to achieve.

First of all the string is a binary string like this:

binStr = '1001011001110110011011001101001011001....'

So in the first iteration, the first key of my dictionary will be set with the first two characters of the string in a shape of list

'key1':[['1','0']]

Then the second key of my dictionary is set with the next two chars.

'key2':[['0','1']]

And so on until I have no more keys, then in the second iteration my keys will have the whatever next two values in the string and set the second list so I'll have something like this:

'key1':[['1','0'],['0','1']]
'key2':[['0','1'],['0','0']

I tried to do something like the following in the beginning but python can't use list index assigment on the fly.

i = 0
for gr in range(2):
   for ch in range(2):
       mydict['key1'][gr][ch] = binStr[i]
       i += 1
8
  • 1
    How does that string become that dictionary? Commented Jun 30, 2014 at 18:58
  • @Matt the string is a binary string coming from reading a file, I just wanted to note that is a long string, so I cannot choose how it was built. Commented Jun 30, 2014 at 19:03
  • @JamieCockburn the string and the dictionary are separate things, each char of the string is supposed to replace 'l1v1', 'l1v2',... values in the list of lists. Commented Jun 30, 2014 at 19:04
  • And the keys are from? Commented Jun 30, 2014 at 19:10
  • @JamieCockburn I've updated my question, the last code will give you an idea of what I'm trying to do but of course it won't work in python Commented Jun 30, 2014 at 19:20

3 Answers 3

1

You could do something like this:

def a(s):
    d = {}
    for i, c in enumerate(s):
        if not i % 4:
            a = [] 
            d['key%s' % ((i/4) + 1)] = a
        if not i % 2:
            b = []
            a.append(b)
        b.append(c)
    return d

Usage:

>>> print a('a_very_very_very_very_very_very_very_long_string.....')
{'key9': [['v', 'e'], ['r', 'y']], 'key8': [['e', 'r'], ['y', '_']], 'key3': 
[['e', 'r'], ['y', '_']], 'key2': [['r', 'y'], ['_', 'v']], 'key1': [['a', '_'],
['v', 'e']], 'key7': [['r', 'y'], ['_', 'v']], 'key6': [['y', '_'], ['v', 'e']],
'key5': [['_', 'v'], ['e', 'r']], 'key4': [['v', 'e'], ['r', 'y']], 'key14':
[['.']], 'key13': [['.', '.'], ['.', '.']], 'key12': [['r', 'i'], ['n', 'g']],
'key11': [['g', '_'], ['s', 't']], 'key10': [['_', 'l'], ['o', 'n']]}
Sign up to request clarification or add additional context in comments.

1 Comment

I made small modifications to suit my needs and it worked, thanks
1

Perhaps not that pythonic, but simple at least, would be to iterate through the string's indices, appending the character pairs to the relevant list within a list of lists. The list of lists is finally converted to a dictionary.

number_of_keys = 15

def get_dict(input_string):
    lists = [[] for _ in range(number_of_keys)]
    for i in range(0, len(input_string), 2):
        lists[int(i/2) % number_of_keys].append(list(input_string[i:i+2]))
    return {'key{}'.format(i+1): L for i, L in enumerate(lists)}

Alternatively you could use a comprehension based on a range of the relevant indices.

def get_dict9(input_string):
    return {'key{}'.format(i + 1): 
        [list(input_string[j:j+2]) 
        for j in range(i * 2, len(input_string), number_of_keys * 2)] 
        for i in range(number_of_keys)}

Comments

0

It could just be me, but I am unclear what you're going after with the correlation to keys and values. HOWEVER, you can nest for..in statements in list comprehensions to produce a similar effect.

Again, this is an example based on having no idea what your keys and values actually have to do with each other.

>>> mydict = {}
>>> for x in range(0, 4):
...     mydict["key{}".format(x)] = ["l{}v{}".format(x, i) for i in range(0, 3)] 
... 
>>> mydict
{'key3': ['l3v0', 'l3v1', 'l3v2'], 'key2': ['l2v0', 'l2v1', 'l2v2'], 'key1': ['l1v0', 'l1v1', 'l1v2'], 'key0': ['l0v0', 'l0v1', 'l0v2']}
>>> 

If your values just iterate through the same pattern, then they too can be subject to their own nested list comprehension.

>>> mydict = {}
>>> for x in range(0, 4):
...     mydict["key{}".format(x)] = ["l{}v{}".format(i, j) for i in (1, 2) for j in (1, 2)]
... 
>>> mydict
{'key3': ['l1v1', 'l1v2', 'l2v1', 'l2v2'], 'key2': ['l1v1', 'l1v2', 'l2v1', 'l2v2'], 'key1': ['l1v1', 'l1v2', 'l2v1', 'l2v2'], 'key0': ['l1v1', 'l1v2', 'l2v1', 'l2v2']}
>>> 

The clincher to these patterns is the

["{}{}".format(i, j) for i in my_container for j in my_other_container]

In this way you iterate over two values and create one pair for each iteration of the values.

You also have the mydict.fromkeys(keys, values) method which returns a dict with the described key-value pairs. Not certain that it is still 'as pythonic' as you would like, but a one-liner that returns a similar dict would look something like

>>> newdict = mydict.fromkeys(["key{}".format(x) for x in range(0, 5)], ["l{}v{}".format(i, j) for i in (1, 2) for j in (3, 4)])
>>> newdict
{'key3': ['l1v3', 'l1v4', 'l2v3', 'l2v4'], 'key2': ['l1v3', 'l1v4', 'l2v3', 'l2v4'], 'key1': ['l1v3', 'l1v4', 'l2v3', 'l2v4'], 'key0': ['l1v3', 'l1v4', 'l2v3', 'l2v4'], 'key4': ['l1v3', 'l1v4', 'l2v3', 'l2v4']}
>>> 

Breaking it up on separate lines makes it more readable:

mykeys = ['key{}'.format(x) for x in range(0, 5)]
myvals = ['l{}v{}'.format(i, j) for i in (1, 2) for j in range(1, 2)]
mydict = {}.fromkeys(mykeys, myvals)

EDIT: you can step through your string in a few ways; again, with list comprehension, you can use:

vals = [myStr[x:x+2] for x in range(0, len(myStr)) if x % 2 == 0]

For example:

>>> mystr = "abcdefghi"
>>> STEP = 2
>>> group = [mystr[x:x+STEP] for x in range(0, len(mystr)) if x % STEP == 0]
>>> group
['ab', 'cd', 'ef', 'gh', 'i']
>>> 

Note that it fails gracefully if there are an uneven number of characters, as seen above. Essentially, STEP can be whatever size of string chunk you're looking to extract.

1 Comment

Sorry, I din't make myself clear, can you re-read my question please? I've added more info

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.