简体   繁体   中英

I'm trying to figure out a way to multiply the values of two dictionaries, one of which contains lists

I made the mother of spaghetti code here. This is supposed to multiply the key and/or values two dictionaries (kv1, and kv2), by specifying which (factor1, factor2) and then pruning non-multiplicable results (if pruning is 1) according to what the pruner is (eg 0 or []).

So here's what I'm trying to do:

  1. Figuring out an easier way to assign factor1 and factor2 to their appropriate k1/k2/v1/v2

  2. Trying to zip properly since adsVal is a dictionary containing lists while valSet is a dictionary containing strings.

  3. Trying to multiply the values within each list by their respective string in valSet (so value 5 in every list list in adsVal would be multiplied by the fifth value of valSet )

  4. Figuring out how to turn everything that cannot be multiplied (ie any string that cannot be int()) into the pruner (eg 0) or at least deleting it along with its key

The code is:

def multDict(kv1, kv2, factor1, factor2, pruning, pruner):
    # This multiplies something in two dictionaries
    # With pruning on, null values become the pruner
    if factor1 == 'k1':
        factor1 = kv1.keys()
    elif factor1 == 'k2':
        factor1 = kv2.keys()
    elif factor1 == 'v1':
        factor1 = kv1.values()
    elif factor1 == 'v2':
        factor1 = kv2.values()
    if factor2 == 'k1':
        factor2 = kv1.keys()
    elif factor2 == 'k2':
        factor2 = kv2.keys()
    elif factor2 == 'v1':
        factor2 = kv1.values()
    elif factor2 == 'v2':
        factor2 = kv2.values()
    x3 = []
    for x1 in factor1:
        zipped = zip(x1, factor2)
        for y1, x2 in zipped:
            printtxt(x2)
            try:
                int(y1)
                int(x2)
            except:
                pass
            else:
                print(int(y1)*int(x2))
    return x3

print(multDict(adsVal, valSet, 'v1', 'v2', 1, 0))

Anything will do, I'm just trying to learn. Thanks.

Sample inputs:

adsVal = {'Students': ['inactive', '3'], 'Campaign 1': ['not_delivering', '']}

valSet = {'Delivery': [''], 'Results': ['1000']}

Sample output:

x3 = {'Students': ['0', '3000'], 'Campaign 1: ['0', '0']
import collections

def mul_maybe_ints(a, b, pruner=None):
    try:
        return int(a)*int(b)
    except ValueError:
        return pruner

def strings_times_strings(aa, ab, pruner=None):
    return [mul_maybe_ints(a, b, pruner) for a,b in zip(aa,ab)]

def lists_times_strings(aa, sa, pruner=None):
    return [[mul_maybe_ints(el, s, pruner) for el in a] for a,s in zip(aa,sa)]


# example usage
adsVal = collections.OrderedDict()
adsVal['Students'] = ['inactive', '3']
adsVal['1'] = ['not_delivering', '']

valDict = collections.OrderedDict()
valDict['Delivery'] = '50'
valDict['Results'] = '1000'

result = lists_times_strings(adsVal.values(), valDict.values(), 0)
print( result )  # [[0, 150], [0, 0]]
print( { k : v for k,v in zip(adsVal, result) } )  # {'Students': [0, 150], '1': [0, 0]}

print( strings_times_strings(adsVal.keys(), valDict.values(), 0) )  # [0, 1000]

Some considerations:

  • It's still not entirely clear to me what you specifically want to do
  • As I said in the comments, a dictionary doesn't have a "fifth" element as it is unordered, which is why I use an OrderedDict
  • I always prune since multiplying two non-integers isn't a defined operation
  • This gives you only lists back, so you have to build the dictionary at the call site (see example, you could wrap this into its own function too)

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