-1

The question is how to parse dictionary by key extract values based on max and low value. Then compare values in it, and add some key, value based on calculation. Maybe the question is messy but I will provide more explanation with code.

json object

[
    {
        "YCI": 0.014076729909151329,
        "TCI": 0.5610661498232027,
        "FCI": 0.327632092582722,
        "TFCI": 3.04906430661623,
        "naziv": "HDZ",
        "YCSI": 14.49723089452966
    },
    {
        "YCI": 0.04249999676677044,
        "TCI": 0.33129318126147167,
        "FCI": 1.677073944380761,
        "TFCI": 4.326953034001479,
        "naziv": "HNS",
        "YCSI": 56.80909574468085
    },
    {
        "YCI": 0,
        "TCI": 0.40603351151808614,
        "FCI": 0,
        "TFCI": 12.61045547126369,
        "naziv": "HSP AS",
        "YCSI": 0
    },
    {
        "YCI": 2.231205214448367,
        "TCI": 0,
        "FCI": 0,
        "TFCI": 0,
        "naziv": "HSS",
        "YCSI": 949.343111111111
    }
]

Ok, this is my dictionary. Now how to compare keys in dictionary:

  • YCI
  • TCI
  • FCI
  • TFCI
  • naziv
  • YSCI

with each other based on their values. If value YCI has highest value then YCI, it should set number 1 in the new dictionary, and that logic is also applied to other keys in dictionary. The output would be something like:

json-output

  [
    {
        "YCI": 3,
        "TCI": 1,
        "FCI": 2,
        "TFCI": 3,
        "naziv": "HDZ",
        "YCSI": 3
    },
    {
        "YCI": 2,
        "TCI": 3,
        "FCI": 1,
        "TFCI": 2,
        "naziv": "HNS",
        "YCSI": 2
    },
    {
        "YCI": 0,
        "TCI": 2,
        "FCI": 0,
        "TFCI": 1,
        "naziv": "HSP AS",
        "YCSI": 0
    },
    {
        "YCI": 1,
        "TCI": 0,
        "FCI": 0,
        "TFCI": 0,
        "naziv": "HSS",
        "YCSI": 1
    }
]

The highest value gets number 1 and the lowest value depends on how many objects dictionary contains.

code-try

print max(nvalues[0].iteritems(), key=operator.itemgetter(1))[1]

With this code I can extract the highest value, but how to sort dictionary within its values. If you could give me some logic to solve this, I would appreciate.

Marin
  • 1,098
  • 14
  • 33
  • regarding sorting read this http://stackoverflow.com/questions/613183/sort-a-python-dictionary-by-value – midori Sep 30 '15 at 21:43
  • it's a bit confusing. can you add step by step explanation? for the first dictionary, YCSI has the highest value, but in the new dictionary its value is not set to 1. what are the logic for setting values to 0,2,3? – marmeladze Sep 30 '15 at 21:46
  • I think the easiest solution is to sort the list of dict `N` times (one for each property you want to "rank") and then replace the values with the index in the sorted array ... – mgilson Sep 30 '15 at 21:50
  • The indices in your sample output do not match the semantics you describe. Please correct them, so we have some idea of what you want to do. – Prune Sep 30 '15 at 22:13
  • Output sample changed. – Marin Sep 30 '15 at 22:18

2 Answers2

1
def rank_by_value(list_dicts):

    from operator import  itemgetter
    from itertools import groupby

    nums = []
    symbs = []

    # separting keys, values into two lists
    # one for numeric values, the other for string values
    for indx, d in enumerate(list_dicts):
        for k, val in d.items():
            if type(val) in (int,float):
                nums.append((indx,k,val))
            else:
                symbs.append((indx,{k:val}))

    groups = []
    # grouping lists
    for k, g in groupby(nums, key=itemgetter(0)):
        groups.append(list(g))

    allData = []
    # sorting lists by by each dictionry values and assinging ranks
    for g in groups:
        sort_ed = sorted(g, key=itemgetter(2), reverse=True)
        ranked = [ list((t,i+1)) for i,t in enumerate(sort_ed)]
        allData.append(ranked)
        ranked = []

    # remove numerical data
    for zero in allData:
        for i, el in enumerate(zero):
           one,two, _ = el[0]
           zero[i] = one,(two, el[1])

    # now creating dictionaries anew
    list_of_dict = []
    dict_temp = {}

    for i, (el, sy) in enumerate(zip(allData, symbs)) :
        for l in el:
            name_, rank_ = l[1]
            dict_temp[name_] = rank_
        dict_temp.update(symbs[i][1])
        list_of_dict.append(dict_temp)
        dict_temp = {}



    return list_of_dict



 for el in rank_by_value(jsn):
    print(el)


{'TCI': 3, 'YCSI': 1, 'naziv': 'HDZ', 'YCI': 5, 'FCI': 4, 'TFCI': 2}
{'TCI': 4, 'YCSI': 1, 'naziv': 'HNS', 'YCI': 5, 'FCI': 3, 'TFCI': 2}
{'TCI': 2, 'YCSI': 3, 'naziv': 'HSP AS', 'YCI': 4, 'FCI': 5, 'TFCI': 1}
{'TCI': 3, 'YCSI': 1, 'naziv': 'HSS', 'YCI': 2, 'FCI': 4, 'TFCI': 5}
LetzerWille
  • 5,355
  • 4
  • 23
  • 26
0
import six

raw_object = [
    {
        "YCI": 0.014076729909151329,
        "TCI": 0.5610661498232027,
        "FCI": 0.327632092582722,
        "TFCI": 3.04906430661623,
        "naziv": "HDZ",
        "YCSI": 14.49723089452966
    },
    {
        "YCI": 0.04249999676677044,
        "TCI": 0.33129318126147167,
        "FCI": 1.677073944380761,
        "TFCI": 4.326953034001479,
        "naziv": "HNS",
        "YCSI": 56.80909574468085
    },
    {
        "YCI": 0,
        "TCI": 0.40603351151808614,
        "FCI": 0,
        "TFCI": 12.61045547126369,
        "naziv": "HSP AS",
        "YCSI": 0
    },
    {
        "YCI": 2.231205214448367,
        "TCI": 0,
        "FCI": 0,
        "TFCI": 0,
        "naziv": "HSS",
        "YCSI": 949.343111111111
    }
]

#make a list (equal in length to original object) of empty dictionaries
ranks_object = [{} for i in raw_object]

#iterate through each key in the first dictionary
#(I assumed that all dictionaries will have the same keys)
for key in raw_object[0]:

    #create a list with the value for this key from all dictionaries 
    raw_list = [group[key] for group in raw_object]

    #sort and store the list
    sorted_raw_list = sorted(raw_list)

    #create a list of the ranks of each of the raw values
    #if the value is greater than zero, a value's rank is the length
    #  of the raw list minus the index of the value in the sorted list
    #otherwise, the rank should be 0 (as indicated by OP's desired output)
    ranks = [len(raw_list) - sorted_raw_list.index(value) if value > 0 else 0 for value in raw_list]

    #iterate through each rank in the ranks list (with access to the
    #  list index, which will be used to make sure that the rank is
    #  inserted into the proper dictionary)
    for index, rank in enumerate(ranks):

        #if the value for the key in the first dictionary is a string,
        #  insert the original value with the key
        #(I assumed that if one dictionary has a string value for a
        #  certain key, all of the dictionaries do as well)
        if isinstance(raw_object[0][key], six.string_types):
            ranks_object[index][key] = raw_object[index][key]

        #otherwise insert the rank with the key
        else:
            ranks_object[index][key] = rank

#display each rank dictionary separately to improve readability
for x in ranks_object:
    print x
Jason
  • 2,725
  • 2
  • 14
  • 22