0

I have a sorted list based on the value for key name as below:

s = [{'name': 'Bart', 'age': 12}, {'name': 'Bart', 'age': 19}, {'name': 'Bart', 'age': 1},{'name': 'Homer', 'age': 30}, {'name': 'Homer', 'age': 12},{'name': 'Simpson', 'age': 19}]

I want to arrange the elements of the list such that dictionaries with the same value for key name do not occur one after the other.

Required output:

[{'name': 'Bart', 'age': 12}, {'name': 'Homer', 'age': 30}, {'name': 'Simpson', 'age': 19}, {'name': 'Bart', 'age': 19}, {'name': 'Homer', 'age': 12}, {'name': 'Bart', 'age': 1}]

OR

[{'name': 'Bart', 'age': 12}, {'name': 'Homer', 'age': 30}, {'name': 'Bart', 'age': 19}, {'name': 'Homer', 'age': 12}, {'name': 'Bart', 'age': 1},{'name': 'Simpson', 'age': 19}]

To get either one of the required outputs I tried using map and lambda The idea was to compare every name element with the next elements name and if they don't match, swap the values and return the resulting list.

Below is the code which I was trying:

map(lambda x: x if x['name']!=next(iter(x))['name'] else None, s)

One thing that did not work is that next(iter(x) did not return the next element. I also want to know why and if the solution can be achieved using map and lambda ?

Vaulstein
  • 20,055
  • 8
  • 52
  • 73
  • 4
    This is not well-posed. For example, if you have 3 Homers and 1 Bart, that's not possible. – Mikael Rousson Jul 22 '16 at 11:15
  • What if it isn't a sorted list? Then the ideal solution would be homer, bart, homer , homer. I only want to separate them as much as I can. Cases where it cannot be avoided, it is fine. – Vaulstein Jul 22 '16 at 11:17
  • Related, if not exact duplicate: http://stackoverflow.com/q/25285792/1639625 – tobias_k Jul 22 '16 at 11:21
  • @tobias_k: Thanks! this seems helpful. I now need to do the same for a list of dictionaries. – Vaulstein Jul 22 '16 at 11:25
  • `next(iter(x))` will create a _new_ `iter` and get the `next` element from that, i.e. it will _always_ return the _first_ element of the iterable. – tobias_k Jul 22 '16 at 11:29

1 Answers1

1

I wrote this according to your requirements, though it is not as condensed:

s = [{'name': 'Bart', 'age': 12}, {'name': 'Bart', 'age': 19}, {'name': 'Bart', 'age': 1},
    {'name': 'Homer', 'age': 30}, {'name': 'Homer', 'age': 12},{'name': 'Simpson', 'age': 19}]

res=[]

for m,n in zip(s, reversed(s)):
    if m!=n:
        res.append(m)
        res.append(n)
    else:       
        res.append(m)
    if len(res)==len(s):
        break

print res

It makes use of the fact that you already have the sorted list.

shiva
  • 2,535
  • 2
  • 18
  • 32
  • This seems good! I like the way you used the sorted and the reverse list to get to the solution. Will test for a few cases. – Vaulstein Jul 22 '16 at 11:42
  • This does not always work. Try with the (also sorted) list `s = [1,1,1,1,2,2,2,2,3,3,3,3]` It will mix the `1`s and `3`s just fine, but then clump all the `2`s together. – tobias_k Jul 22 '16 at 11:44
  • @Vaulstein I am sorry about my answer. I will try to come up with a better solution. – shiva Jul 22 '16 at 15:58