1

I have a python Dictionary

var = {'count': [1, 1, 1, 1, 1],
       'path': ['/media/anurag/Work/search_script/masterfile.txt',
                "/media/anurag/Work/search_script/Women's Running Shoes/Women's Running Shoes_2.csv",
                "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt",
                "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running Shoes_1.csv",
                "/media/anurag/Work/search_script/Men's Running Shoes/output.txt"],
       'modified': [1502974843.8277025, 1501594022.454686, 1501945289.3378062,
                    1501593976.6210368, 1501945143.4162745],
       'row': [9541, 8723, 1664, 506, 2200]}

Now I have to sort based on modified as key. Without disturbing order. I have used pandas for this:

My pandas solution is

In [1]: import pandas as pd

In [2]: var = {'count': [1, 1, 1, 1, 1], 'path': ['/media/anurag/Work/search_script/masterfile.txt', "/media/anurag/Work/search_script/Women's Running Shoes/Women's Running Shoes_2.csv", "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt", "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running Shoes_1.csv", "/media/anurag/Work/search_script/Men's Running Shoes/output.txt"], 'modified': [1502974843.8277025, 1501594022.454686, 1501945289.3378062, 1501593976.6210368, 1501945143.4162745], 'row': [9541, 8723, 1664, 506, 2200]}

In [3]: search_result = pd.DataFrame.from_dict(var)

In [4]: search_result.sort_values('modified', inplace=True, ascending=False)

In [5]: search_result
Out[5]: 
   count      modified                                               path  \
0      1  1.502975e+09    /media/anurag/Work/search_script/masterfile.txt   
2      1  1.501945e+09  /media/anurag/Work/search_script/Men's Running...   
4      1  1.501945e+09  /media/anurag/Work/search_script/Men's Running...   
1      1  1.501594e+09  /media/anurag/Work/search_script/Women's Runni...   
3      1  1.501594e+09  /media/anurag/Work/search_script/Men's Running...   

    row  
0  9541  
2  1664  
4  2200  
1  8723  
3   506 

Can I do this without pandas?

cs95
  • 379,657
  • 97
  • 704
  • 746
Anurag Misra
  • 1,516
  • 18
  • 24

5 Answers5

4

You can store the objects as a dictionary mapping, and then sort the list of such objects with the appropriate sorting criterion (specified by key). Something like below -

var = {'count': [1, 1, 1, 1, 1], 'path': ['/media/anurag/Work/search_script/masterfile.txt', "/media/anurag/Work/search_script/Women's Running Shoes/Women's Running Shoes_2.csv", "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt", "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running Shoes_1.csv", "/media/anurag/Work/search_script/Men's Running Shoes/output.txt"], 'modified': [1502974843.8277025, 1501594022.454686, 1501945289.3378062, 1501593976.6210368, 1501945143.4162745], 'row': [9541, 8723, 1664, 506, 2200]}

objects = [{field: value[i] for field,value in var.items()}
           for i in range(len(var['count']))]

objects.sort(key=itemgetter('modified')) # you may add reverse=True as per need
shad0w_wa1k3r
  • 12,955
  • 8
  • 67
  • 90
1

Here is my suggestion, which uses one dict comprehension to build the output:

import pprint

var = {'count': [1, 1, 1, 1, 1],
       'modified': [1502974843.8277025,
                    1501594022.454686,
                    1501945289.3378062,
                    1501593976.6210368,
                    1501945143.4162745],
       'path': ['/media/anurag/Work/search_script/masterfile.txt',
                "/media/anurag/Work/search_script/Women's Running Shoes/Women's "
                'Running Shoes_2.csv',
                "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt",
                "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running "
                'Shoes_1.csv',
                "/media/anurag/Work/search_script/Men's Running Shoes/output.txt"],
       'row': [9541, 8723, 1664, 506, 2200]}

output = {k: [i[1] for i in sorted(enumerate(v),
                                   key=lambda x: var["modified"][x[0]],
                                   reverse=True)]
              for k, v in var.items()}

pprint.pprint(output)

This has the output:

{'count': [1, 1, 1, 1, 1],
 'modified': [1502974843.8277025,
              1501945289.3378062,
              1501945143.4162745,
              1501594022.454686,
              1501593976.6210368],
 'path': ['/media/anurag/Work/search_script/masterfile.txt',
          "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt",
          "/media/anurag/Work/search_script/Men's Running Shoes/output.txt",
          "/media/anurag/Work/search_script/Women's Running Shoes/Women's "
          'Running Shoes_2.csv',
          "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running "
          'Shoes_1.csv'],
 'row': [9541, 1664, 2200, 8723, 506]}

As you can see, the output with my code is another dictionary in the same form as your input, but where each list has been sorted according to what I think you want. As you can see, the "row" key-values correspond to your sample output.

Izaak van Dongen
  • 2,450
  • 13
  • 23
1

The following converts your dict to a list of tuples and sorts it based on the value of the modified key.

var = {'count': [1, 1, 1, 1, 1], 'path': ['/media/anurag/Work/search_script/masterfile.txt', "/media/anurag/Work/search_script/Women's Running Shoes/Women's Running Shoes_2.csv", "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt", "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running Shoes_1.csv", "/media/anurag/Work/search_script/Men's Running Shoes/output.txt"], 'modified': [1502974843.8277025, 1501594022.454686, 1501945289.3378062, 1501593976.6210368, 1501945143.4162745], 'row': [9541, 8723, 1664, 506, 2200]}
inv = list(zip(*var.values()))
ind = next(i for i, x in enumerate(inv[0]) if isinstance(x, float))  # note 1
res = sorted(inv, key=lambda x: x[ind])  # note 2
print(res)

# outputs:
 [(506, 1, "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running Shoes_1.csv", 1501593976.6210368),
 (8723, 1, "/media/anurag/Work/search_script/Women's Running Shoes/Women's Running Shoes_2.csv", 1501594022.454686), 
 (2200, 1, "/media/anurag/Work/search_script/Men's Running Shoes/output.txt", 1501945143.4162745), 
 (1664, 1, "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt", 1501945289.3378062), 
 (9541, 1, '/media/anurag/Work/search_script/masterfile.txt', 1502974843.8277025)]
  • Note 1: There are no guarantees on the order in which the items in values() are going to be returned. As a result we must look for the values of the modified key and make a note of their index to use later while sorting.
  • Note 2: If it is the opposite order you are looking for, pass the reverse=True argument to the sorted function.
Ma0
  • 15,057
  • 4
  • 35
  • 65
1

FWIW, here's another way to do this in plain Python, with the output in the same format as the input: a dictionary of lists. I use json.dumps to make the output look nice. This code isn't quite as compact as Izaak van Dongen's, but I think it may be a little more readable. We use zip(*...) to transpose the lists, and again to transpose them back to rebuild the dict. IOW, we transpose columns to rows, sort the rows, and transpose them back to columns.

from operator import itemgetter
from json import dumps

var = {
    "count": [1, 1, 1, 1, 1],
    "path": [
        "/media/anurag/Work/search_script/masterfile.txt",
        "/media/anurag/Work/search_script/Women's Running Shoes/Women's Running Shoes_2.csv",
        "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt",
        "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running Shoes_1.csv",
        "/media/anurag/Work/search_script/Men's Running Shoes/output.txt",
    ],
    "modified": [
        1502974843.8277025,
        1501594022.454686,
        1501945289.3378062,
        1501593976.6210368,
        1501945143.4162745,
    ],
    "row": [9541, 8723, 1664, 506, 2200],
}

keys = var.keys()
idx = list(keys).index("modified")
a = sorted(zip(*var.values()), key=itemgetter(idx), reverse=True)
result = {k: list(v) for k, v in zip(keys, zip(*a))}

print(dumps(result, indent=4))

output

{
    "count": [
        1,
        1,
        1,
        1,
        1
    ],
    "path": [
        "/media/anurag/Work/search_script/masterfile.txt",
        "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt",
        "/media/anurag/Work/search_script/Men's Running Shoes/output.txt",
        "/media/anurag/Work/search_script/Women's Running Shoes/Women's Running Shoes_2.csv",
        "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running Shoes_1.csv"
    ],
    "modified": [
        1502974843.8277025,
        1501945289.3378062,
        1501945143.4162745,
        1501594022.454686,
        1501593976.6210368
    ],
    "row": [
        9541,
        1664,
        2200,
        8723,
        506
    ]
}
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
0

For your dictionary,

var = {'count': [1, 1, 1, 1, 1],
       'path': ['/media/anurag/Work/search_script/masterfile.txt',
                "/media/anurag/Work/search_script/Women's Running Shoes/Women's Running Shoes_2.csv",
                "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt",
                "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running Shoes_1.csv",
                "/media/anurag/Work/search_script/Men's Running Shoes/output.txt"],
       'modified': [1502974843.8277025, 1501594022.454686, 1501945289.3378062,
                    1501593976.6210368, 1501945143.4162745],
       'row': [9541, 8723, 1664, 506, 2200]}

How about this one line?

var['row'] = [x for (y,x) in sorted(zip(var['modified'],var['row']),reverse=True)]

output:

{'count': [1, 1, 1, 1, 1],
 'modified': [1502974843.8277025,
              1501594022.454686,
              1501945289.3378062,
              1501593976.6210368,
              1501945143.4162745],
 'path': ['/media/anurag/Work/search_script/masterfile.txt',
          "/media/anurag/Work/search_script/Women's Running Shoes/Women's "
          'Running Shoes_2.csv',
          "/media/anurag/Work/search_script/Men's Running Shoes/masterfile.txt",
          "/media/anurag/Work/search_script/Men's Running Shoes/Men's Running "
          'Shoes_1.csv',
          "/media/anurag/Work/search_script/Men's Running Shoes/output.txt"],
 'row': [9541, 1664, 2200, 8723, 506]}

Explanations:

>>> a = [1,2,3,4]
>>> sorted(a)
[1, 2, 3, 4]
>>> b = [1,23,9,4]
>>> sorted(b)
[1, 4, 9, 23]
>>> 
>>> sorted(zip(b,a))
[(1, 1), (4, 4), (9, 3), (23, 2)]

Now as you can see sorted only sorts based upon the first value in the tuple So depending upon it you can get the second value using a simple list comprehension. (which will be sorted based on first one)

>>> result = [ x for (y,x) in  above_list]
>>> result
[1, 4, 3, 2]

The same is what is happening above in the solution. Hope this helps :)

void
  • 2,571
  • 2
  • 20
  • 35
  • how `var['row'] = [x for (y,x) in sorted(zip(var['modified'],var['row']),reverse=True)]` its returning that value.? – Anurag Misra Aug 21 '17 at 12:36
  • This link might be useful https://stackoverflow.com/questions/6618515/sorting-list-based-on-values-from-another-list – void Aug 21 '17 at 12:37