Palawakin ang isang dict na naglalaman ng mga item sa listahan sa isang listahan ng mga dict pairs

r3robertson 06/24/2018. 6 answers, 276 views
python python-2.7 dictionary list-comprehension dictionary-comprehension

Kung mayroon akong diksyunaryo na naglalaman ng mga listahan sa isa o higit pa sa mga halaga nito:

data = {
  'a':0,
  'b':1,
  'c':[0, 1, 2],
  'pair':['one','two']
} 

Paano ako makakakuha ng isang listahan ng mga tuples ng dict na ipinares sa pamamagitan ng pair at iterating sa c , sa lahat ng iba pang natitirang pare-pareho? Hal

output = [
    ({
        'a':0,
        'b':1,
        'c':0,
        'pair':'one'
    },
    {
        'a':0,
        'b':1,
        'c':0,
        'pair':'two'
    }),
    ({
        'a':0,
        'b':1,
        'c':1,
        'pair':'one'
    },
    ...
] 

6 Answers


davidshere 06/24/2018.

Well, ito ay hindi pakiramdam lalo na matikas, ngunit maaari mong gamitin ang isang nested para sa loop o listahan ng pag-unawa:

output = []
for i in data['c']:
  output.append(tuple({'a': 0, 'b': 1, 'c': i, 'pair': p} for p in data)) 

o

output = [tuple({'a': 0, 'b': 1, 'c': i, 'pair': p} for p in data['pair']) for i in data['c']] 

Ang isang mas malinis na solusyon ay maaaring paghiwalayin ang henerasyon ng bahagi dict sa isang function, tulad nito:

def gen_output_dict(c, pair):
  return {'a': 0, 'b': 1, 'c': c, 'pair': pair}

output = []
for i in data['c']:
  output.append(tuple(gen_output_dict(i, p) for p in data['pair'])) 

Olivier Melançon 06/24/2018.

Maaari mong gamitin ang itertools.product sa mga halaga ng listahan at subaybayan ang susi kung saan nagmula ang bawat elemento. Dahil ang susi 'pair' ay may isang espesyal na kahulugan, dapat mong ituring ito nang hiwalay.

Code

from itertools import product

def unzip_dict(d):
    keys = [k for k, v in d.items() if isinstance(v, list) and k != 'pair']
    values = [d[k] for k in keys]

    for values in product(*values):
        yield tuple({**d, **dict(zip(keys, values)), 'pair': pair} for pair in d['pair']) 

Halimbawa

data = {
    'a': 0,
    'c': [1, 2],
    'pair': ['one', 'two']
}

print(*unzip_dict(data)) 

Output

({'a': 0, 'c': 1, 'pair': 'one'}, {'a': 0, 'c': 1, 'pair': 'two'})
({'a': 0, 'c': 2, 'pair': 'one'}, {'a': 0, 'c': 2, 'pair': 'two'}) 

Abdou 06/24/2018.

Ang sumusunod ay lubos na pinalawig na solusyon:

data = {
  'a':0,
  'b':1,
  'c':[0, 1, 2],
  'pair':['one','two']
}

# Get the length of the longest sequence
length = max(map(lambda x: len(x) if isinstance(x, list) else 1, data.values()))

# Loop through the data and change scalars to sequences
# while also making sure that smaller sequences are stretched to match
# or exceed the length of the longest sequence
for k, v in data.items():
    if isinstance(v, list):
        data[k] = v * int(round(length/len(v), 0))
    else:
        data[k] = [v] * length

# Create a dictionary to keep track of which outputs
# need to end up in which tuple
seen = dict.fromkeys(data.get('pair'), 0)
output = [tuple()] * len(seen)

# Loop through the data and place dictionaries in their
# corresponding tuples.
for v in zip(*data.values()):
        d = dict(zip(data, v))
        output[seen[d.get('pair')]] += (d,)
        seen[d.get('pair')] += 1

print(output) 

Ang ideya ay ang pag-convert ng mga scalar sa iyong data sa mga pagkakasunud-sunod na ang haba ay tumutugma sa pinakamahabang pagkakasunud-sunod sa orihinal na data. Samakatuwid, ang unang bagay na ginawa ko ay nakatalaga sa length variable ang sukat ng pinakamahabang pagkakasunud-sunod. Gamit ang kaalaman na iyon, ikinalulungkot namin ang orihinal na data at pahabain ang mga umiiral na mga pagkakasunud-sunod upang tumugma sa laki ng pinakamahabang pagkakasunud-sunod habang nagko-convert ang mga scalar sa mga pagkakasunud-sunod. Kapag tapos na, lumipat kami sa pagbuo ng output variable. Ngunit una, lumikha kami ng isang diksyunaryo na tinatawag na nakakatulong upang tulungan kaming lumikha ng isang listahan ng mga tuple at subaybayan kung aling pangkat ng mga diksyunaryo ang nagtatapos kung saan ang tuple. Kung gayon, ito ay nagbibigay-daan sa amin na magpatakbo ng isang huling loop upang ilagay ang mga grupo ng mga diksyunaryo sa kanilang mga kaukulang tuple.

Ang kasalukuyang output ay mukhang mga sumusunod:

[({'a': 0, 'b': 1, 'c': 0, 'pair': 'one'},
  {'a': 0, 'b': 1, 'c': 1, 'pair': 'two'}),
 ({'a': 0, 'b': 1, 'c': 2, 'pair': 'one'},)] 

Mangyaring ipaalam sa akin kung kailangan mo ng karagdagang mga detalye ng paglilinaw. Kung hindi, umaasa ako na naglilingkod ito sa ilang layunin.


Rishikesh Agrawani 06/24/2018.

@r3robertson , Maaari mo ring subukan ang code sa ibaba. Ang code ay batay sa konsepto ng list comprehension , & deepcopy() operation sa Python.

Suriin ang Mababaw na kopya kumpara sa deepcopy sa Python .

import pprint;
import copy;

data = {
    'a': 0,
    'b': 1,
    'c': [0, 1, 2],
    'pair': ['one','two'],
};

def get_updated_dict(data, index, pair_name):
    d = copy.deepcopy(data);
    d.update({'c': index, 'pair': pair_name});
    return d;

output = [tuple(get_updated_dict(data, index, pair_name) for pair_name in data['pair']) for index in data['c']];

# Pretty printing the output list.
pprint.pprint(output, indent=4); 

Output »

[   (   {   'a': 0, 'b': 1, 'c': 0, 'pair': 'one'},
        {   'a': 0, 'b': 1, 'c': 0, 'pair': 'two'}),
    (   {   'a': 0, 'b': 1, 'c': 1, 'pair': 'one'},
        {   'a': 0, 'b': 1, 'c': 1, 'pair': 'two'}),
    (   {   'a': 0, 'b': 1, 'c': 2, 'pair': 'one'},
        {   'a': 0, 'b': 1, 'c': 2, 'pair': 'two'})] 

Pretty printing gamit ang json module »

Note: -convert ang Tuple sa listahan dito bilang mga tuple ay hindi sinusuportahan sa loob ng JSON.

import json;
print(json.dumps(output, indent=4)); 

Output »

[
    [
        {
            "a": 0,
            "c": 0,
            "b": 1,
            "pair": "one"
        },
        {
            "a": 0,
            "c": 0,
            "b": 1,
            "pair": "two"
        }
    ],
    [
        {
            "a": 0,
            "c": 1,
            "b": 1,
            "pair": "one"
        },
        {
            "a": 0,
            "c": 1,
            "b": 1,
            "pair": "two"
        }
    ],
    [
        {
            "a": 0,
            "c": 2,
            "b": 1,
            "pair": "one"
        },
        {
            "a": 0,
            "c": 2,
            "b": 1,
            "pair": "two"
        }
    ]
] 

Ajax1234 06/24/2018.

Maaari mong gamitin ang itertools :

import itertools
data = {
  'a':0,
  'b':1,
  'c':[0, 1, 2],
  'pair':['one','two']
}
def expand_dict(data):
   grouped = [a for a, b in data.items() if isinstance(b, list)]
   p = [[a, list(b)] for a, b in itertools.groupby(itertools.product(*[data[i] for i in grouped]), key=lambda x:x[0])]
   return [tuple({**data, **dict(zip(grouped, i))} for i in c) for _, c in p]

print(expand_dict(data)) 

Output:

[({'a': 0, 'b': 1, 'c': 0, 'pair': 'one'}, {'a': 0, 'b': 1, 'c': 0, 'pair': 'two'}), 
 ({'a': 0, 'b': 1, 'c': 1, 'pair': 'one'}, {'a': 0, 'b': 1, 'c': 1, 'pair': 'two'}), 
 ({'a': 0, 'b': 1, 'c': 2, 'pair': 'one'}, {'a': 0, 'b': 1, 'c': 2, 'pair': 'two'})] 

Ang solusyon na ito ay gagana rin sa input na may maraming mga posibleng listahan ng mga halaga:

data = {'a':[5, 6, 1, 3], 'b':1, 'c':[0, 1, 2], 'pair':['one', 'two']}
print(expand_dict(data)) 

Output:

[({'a': 5, 'b': 1, 'c': 0, 'pair': 'one'}, {'a': 5, 'b': 1, 'c': 0, 'pair': 'two'}, {'a': 5, 'b': 1, 'c': 1, 'pair': 'one'}, {'a': 5, 'b': 1, 'c': 1, 'pair': 'two'}, {'a': 5, 'b': 1, 'c': 2, 'pair': 'one'}, {'a': 5, 'b': 1, 'c': 2, 'pair': 'two'}), ({'a': 6, 'b': 1, 'c': 0, 'pair': 'one'}, {'a': 6, 'b': 1, 'c': 0, 'pair': 'two'}, {'a': 6, 'b': 1, 'c': 1, 'pair': 'one'}, {'a': 6, 'b': 1, 'c': 1, 'pair': 'two'}, {'a': 6, 'b': 1, 'c': 2, 'pair': 'one'}, {'a': 6, 'b': 1, 'c': 2, 'pair': 'two'}), ({'a': 1, 'b': 1, 'c': 0, 'pair': 'one'}, {'a': 1, 'b': 1, 'c': 0, 'pair': 'two'}, {'a': 1, 'b': 1, 'c': 1, 'pair': 'one'}, {'a': 1, 'b': 1, 'c': 1, 'pair': 'two'}, {'a': 1, 'b': 1, 'c': 2, 'pair': 'one'}, {'a': 1, 'b': 1, 'c': 2, 'pair': 'two'}), ({'a': 3, 'b': 1, 'c': 0, 'pair': 'one'}, {'a': 3, 'b': 1, 'c': 0, 'pair': 'two'}, {'a': 3, 'b': 1, 'c': 1, 'pair': 'one'}, {'a': 3, 'b': 1, 'c': 1, 'pair': 'two'}, {'a': 3, 'b': 1, 'c': 2, 'pair': 'one'}, {'a': 3, 'b': 1, 'c': 2, 'pair': 'two'})] 

user8700465 06/24/2018.

Hindi masyadong perpekto ngunit narito ang aking solusyon.

data = { 'a':0, 'b':1, 'c':[0, 1, 2], 'pair':['one','two'] }
a,b = data['pair'], data['c']
for t in range(0, len(b)):
  for u in range(0, len(a)):
    for h in a:
        data['c']=b[t]
        data['pair']=a[u]
    print(tuple([data])) 

Related questions

Hot questions

Language

Popular Tags