简体   繁体   中英

Efficiently add values to bidimensional array

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

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']]}

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)}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM