简体   繁体   中英

Python Module: Inconsistent Output

I have a module that is supposed to find the average value given a list of vectors. The problem is that the returned value is inconsistent. Sometimes it gives me the expected output and other times it does not.

def find_average_record(sen_set, voting_dict):
    """
Input: a set of last names, a voting dictionary
Output: a vector containing the average components of the voting records
        of the senators in the input set
    """

    count = len(sen_set)
    total_set = voting_dict[sen_set.pop()]

    for senator in sen_set:
        for vote in voting_dict[senator]:
            total_set[vote] += vote

    return [x/count for x in total_set]

Example:

voting_dict = {'Klein': [-1,0,1], 'Fox-Epstein': [-1,-1,-1], 'Ravella': [0,0,1]} 
find_average_record({'Fox-Epstein','Ravella'}, voting_dict) 
# should =>[-0.5, -0.5, 0.0]

You are using the vote count from each senator as an index into the total votes. Don't do that. Use enumerate() instead. You also need to make a copy of the voting_dict list you assign to total_set to avoid altering the mutable list in place:

def find_average_record(sen_set, voting_dict):
    count = len(sen_set)
    total_set = voting_dict[sen_set.pop()][:]

    for senator in sen_set:
        for i, vote in enumerate(voting_dict[senator]):
            total_set[i] += vote

    return [x/count for x in total_set]

You could also use sum() on each column (use zip() to transpose rows and columns); this avoids altering any of the vote lists in place altogether:

def find_average_record(sen_set, voting_dict):
    count = len(sen_set)
    return [sum(col) / count for col in zip(*(voting_dict[sen] for sen in sen_set))]

Either version now returns the average correctly:

>>> find_average_record({'Fox-Epstein', 'Ravella'}, voting_dict) 
[-0.5, -0.5, 0.0]

Moreover, the lists contained in voting_dict are not altered.

This may be wrong, since you've already accepted Martijn's answer, but I think this is what you want. I changed the senator set argument into a list so that the average values in the vector returned are in the same order as that list (and there is the same number of them).

def find_average_record(sen_list, voting_dict):
    """
Input: a list of senator names, a voting dictionary
Output: a vector containing the average components of the voting records
        of the senators in the input list in the same order
    """
    def average(vector):
        return sum(vector) / len(vector)

    return [average(voting_dict[senator]) for senator in sen_list]

voting_dict = {      'Klein': [-1, 0, 1],
               'Fox-Epstein': [-1,-1,-1],
                   'Ravella': [ 0, 0, 1]}
print(find_average_record(['Fox-Epstein', 'Ravella'], voting_dict))

Output:

[-1.0, 0.3333333333333333]

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