-1

Edited: I need to change the rule. I have a list of dictionaries like this:

A=[{0:[(0,0,2,1),(0,1,2,1)]},{1:(0,1,1,3)},{2:[(1,2,2,2)]},{3:(0,0,1,4),(0,1,1,4),(1,0,1,4)}]

First, I need to count the number of elements in each dictionary. Second, calculate multiply the last two elements for one of the elements in each list(because at each list the last two elements are the same), like this:

M=[(0,2,2) ,(1,3,1) , (2,4,1) , (3,4,3)]

the first element is the key, the second is the multiply of the last two elements, and the third is the number of elements in that list. (I don't need to print this part) then for each list calculate multiply/options, like this:

B=[(0,2/2), (1,3/1), (2,4/1), (3,4/3)]

I need the output to be a list of keys with the large to small the second element:

output: [2, 1, 3, 0]

Does anyone have any idea that could help?

Sara
  • 7
  • 3
  • 3
    Have you tried any solution yet? Please share it and what's not working for you in that. – windstorm Sep 30 '20 at 06:49
  • unfortunately, I have no idea. I don't have much experience in coding and this is complicated for me :( – Sara Sep 30 '20 at 06:51
  • You can define custom sorting rules with the `key` parameter. There are already questions about that on SO, or you can read the [howto](https://docs.python.org/3/howto/sorting.html) – Wups Sep 30 '20 at 07:01
  • Check this answer: https://stackoverflow.com/questions/613183/how-do-i-sort-a-dictionary-by-value – windstorm Sep 30 '20 at 07:02
  • 1
    @Sara, you've changed the post into an entirely new question, invalidating all current answers. I believe you should have created an entirely new post, and left this as it was. Also, you need to present an MRE [https://stackoverflow.com/help/minimal-reproducible-example ]: You should not just post a task and except the SO community to do your work for you. Please provide us with more details of what you've tried and explain why it doesn't work:) – Wololo Oct 01 '20 at 06:24
  • it is not the entire work. It is just manipulating a combination of the list, dictionaries, and tuples. That why it is complicated. And I did many searches via the internet and get stuck in this part of the program. Also, the StackOverflow doesn't let me create a post with a similar topic. – Sara Oct 01 '20 at 06:45
  • @Sara, that's strange. If your follow-up question is sufficiently distinct from this one, then Stack Overflow should happily let you post it. Perhaps you could make a post on Meta describing the situation and what the new question would look like, and you can get advice on how to make the duplicate-question-detector play nicely. – Kevin Oct 01 '20 at 15:43
  • @KevinThank you. I am new to StackOverflow. as the topic has no change(sort based on a custom rule) I've thought that it is ok to change it here to ask people who already seen this post. I have not been known with the mechanisms of acceptance of the answers and so on.. I will get better at creating a post. – Sara Oct 01 '20 at 20:17

3 Answers3

3

New Solution as per edit

t=[{0:[(0,0,2,1),(0,1,2,1)]},{1:[(0,1,1,3)]},{2:[(1,2,2,2)]},{3:[(0,0,1,4),(0,1,1,4),(1,0,1,4)]}]

step_one=[]

for i in t:
    key_list=list(i.keys())
    value_list=list(i.values())
    first=key_list[0]
    second=value_list[0][0][-1]*value_list[0][0][-2]
    third=len(value_list[0])
    step_one.append((first,second,third))

print(step_one) # [(0, 2, 2), (1, 3, 1), (2, 4, 1), (3, 4, 3)]

step_two=[(i,j/k) for i,j,k in step_one]

step_three=[i for i,j in sorted(step_two,key=lambda x:-x[1])]

print(step_three) # [2, 1, 0, 3]

Will this work? Use the key parameter to perform your sort

t=[{0:[(0,0,1,3),(0,1,1,3)]},{1:[(0,1,1,3)]},{3:[(0,0,1,3),(0,1,1,3),(1,0,4,1)]}]
sorted_t=sorted(t,key=lambda x:len(list(x.values())[0]))
result=[list(i.keys())[0] for i in sorted_t]
print(result) # [1, 0, 3]

Breakdown

sorted_t=sorted(t,key=lambda x:len(list(x.values())[0]))

this will sort the list based on "length of first value in the dict" for each element

Result : [{1: [(0, 1, 1, 3)]}, {0: [(0, 0, 1, 3), (0, 1, 1, 3)]}, {3: [(0, 0, 1, 3), (0, 1, 1, 3), (1, 0, 4, 1)]}]

Then iterate through sorted_t and get the "key for each dict in the sorted list", [0] is for indexing the element from the "key list". Otherwise you will end with a list like [[1], [0], [3]]

python_user
  • 5,375
  • 2
  • 13
  • 32
3

If your dictionaries are going to have more than one key then you can utilize this method

from collections import defaultdict

A = [{0: [(0, 0, 1, 3), (0, 1, 1, 3)], 2: [(0, 1, 0, 3)]},
     {1: [(0, 1, 1, 3)], 4: [(0, 1, 3, 3), (1, 1, 1, 2), (1, 1, 4, 1)]},
     {3: [(0, 0, 1, 3), (0, 1, 1, 3), (1, 0, 4, 1)]}
]
dd = defaultdict(list)

for dictionary in A:
    for k, v in dictionary.items():
        dd[len(v)].append(k)

result = [k[1] for k in sorted(dd.items(), key=lambda x: x[0])]
print(result)

Outputs:

[[2, 1], [0], [4, 3]]
woblob
  • 1,349
  • 9
  • 13
2

@python_learner and @woblob beat me to it, and I very much approve of their answers. However, I just wanted to add the an alternative (yet similar) approach which let's you access the the list of tuples after finding the ranks.

By ending up with a list of keys, sorted by their rank, i.e. [1,0,3] you've lost the information of where the list of tuples are.

To recover the list of tuples, you would need to iterate over A again and search for the keys, but that could be problematic if A contains multiple dicts using the same key.

Hence, the following approach conserves the index_of_A for which each key with some rank is found within A.

# I've added missing brackets in the element of A, {3:[..]}
A=[{0:[(0,0,1,3),(0,1,1,3)]},{1:[(0,1,1,3)]},{3:[(0,0,1,3),(0,1,1,3),(1,0,4,1)]}]

# A is a list of dicts
# Each dict has only one (numerical) key,
# -> resolving to a list of tuples

# run over A and create a new Rank dict, where keys are
# the keys from the dicts in A, and values are tuples of
# the ranks and and index in A for which to locate the lists again.
ranks = {}
for index_of_A, dictionary in enumerate(A):
  for key, list_of_tuples in dictionary.items():
    ranks[key] = (len(list_of_tuples), index_of_A)


# https://stackoverflow.com/questions/613183/how-do-i-sort-a-dictionary-by-value
sorted_ranks = {k: v for k, v in sorted(ranks.items(), key=lambda item: item[1])}


# Get Ranks, key and the list of tuples, and perform some work on them..
for key_of_A, (rank, index_of_A) in sorted_ranks.items():
  print("Do some work on: Rank %d | Key %d | List %s" % (rank, key_of_A, str(A[index_of_A])))
  do_some_work(index_of_A)


# The Keys sorted by their ranks
print ("keys sorted by rank: " + str([key for key in sorted_ranks]))

Output:

Rank 1 | Key 1 | List {1: [(0, 1, 1, 3)]}
Rank 2 | Key 0 | List {0: [(0, 0, 1, 3), (0, 1, 1, 3)]}
Rank 3 | Key 3 | List {3: [(0, 0, 1, 3), (0, 1, 1, 3), (1, 0, 4, 1)]}

keys sorted by rank: [1, 0, 3]

EDIT: it is requested in the comments to show how to do some work on the data, so I've added the function below, and added a call to it in the work loop above.

# Added a function for doing some work as requesed in comments
def do_some_work(index_of_A):
  # A is a global variable
  a_dict = A.pop(index_of_A)
  # do whatever with the data ..
Wololo
  • 1,249
  • 1
  • 13
  • 25
  • This is an interesting code, Thank you. But it returns a string. I need a list with integer because I need to pop the elements in the next step. – Sara Oct 01 '20 at 01:22
  • Dear @Sara, what do you mean with *".. it returns a string. I need a list with integer"* ? The code does **not** give you a string, it gives you a new dict with keys, ranks and values (lists). The code just prints it! SO is not a community that does your work for you, it is a community for aiding you with technical aspects of software development. I expect you to be able to replace the `print` of the result with whatever you need to do with the data.. But now you've changed the post entirely making all current answers inadequate. – Wololo Oct 01 '20 at 06:19
  • this part of the code str([key for key in sorted_ranks])) returns string. doesn't it? I am a beginner, sometimes may have basic questions and sometimes I may get stuck in something that seems easy to professionals. I see many basic questions in StackOverflow.If it is boring for you, just ignore it! I didn't ask all my tasks here.. This is a small part of my program on which I have been working for about a week. I am even working on this question too. Another point is that StackOverflow has limitations to create similar topics. Thank you! – Sara Oct 01 '20 at 06:53
  • @Sara, No. The `str()` encapsulation is only for the `print` function to be able to present the `dict` -data structure out to console. It has nothing to do with the end result. You can easily run over the result-dict and `pop` from either `A` or `sorted_ranks` and do some work on the data. Your question is not *boring* me, but people are investing quite some effort trying to help you and it's difficult when you change the entire question into a new one after accepting an answer. I'll end with a friendly suggestion; to take a quick look at https://stackoverflow.com/help/how-to-ask :) – Wololo Oct 01 '20 at 07:23
  • Thank you for your time. I appreciate it. In that case, this code works as it returns me a list. – Sara Oct 01 '20 at 07:35