Nanno
Nanno

Reputation: 111

How to sort a list of lists in Python without having repeated names together

I have the following list with names and ages:

[['John', 8], ['John', 8], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9]]

How to sort it, with Python, in a random way and without having same name next to each other. For example (sorted):

[['John', 8], ['Mary', 7], ['Mike', 9], ['John', 8], ['Mike', 9], ['Mary', 7], ['John', 8]]

My real case has about 250 names and same name does not repeats more than 50 times, that means that always there is a possible solution.

Upvotes: 1

Views: 142

Answers (3)

Nanno
Nanno

Reputation: 111

Thank you for all the answers and suggestions.

Unfortunately I could not adapt any of the proposed solutions to work with my real data, and I had to develop a solution, that you can see and comment here:

Python: sorting a matrix of data (list of lists) to have equal "names" at the biggest distance of each other

Upvotes: 0

Marcus Vdt
Marcus Vdt

Reputation: 112

Simple example with 296 names and without complicated code. Be aware that this code will run forever if you provide unresolvable list, ie. if you lied when you said the list does not contain lots of repetitions of the same names. For your needs, it should work.

Thank you.

import hashlib
import json
import random
mylist=[['John', 8], ['John', 8], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9],['John', 8], ['John', 8], ['Lucas', 17], ['Lucas', 17], ['Lucas', 17], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9],['John', 8], ['John', 8], ['Lucas', 17],['Marcus', 8], ['Marcus', 8], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9],['Marcus', 8], ['Marcus', 8], ['Beto', 17], ['Beto', 17], ['Beto', 17], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9],['Marcus', 8], ['Marcus', 8], ['Beto', 17], ['John', 8], ['John', 8], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9],['John', 8], ['John', 8], ['Lucas', 17], ['Lucas', 17], ['Lucas', 17], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9],['John', 8], ['John', 8], ['Lucas', 17],['Marcus', 8], ['Marcus', 8], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9],['Marcus', 8], ['Marcus', 8], ['Beto', 17], ['Beto', 17], ['Beto', 17], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9],['Marcus', 8], ['Marcus', 8], ['Beto', 17], ['John', 8], ['John', 8], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9],['John', 8], ['John', 8], ['Lucas', 17], ['Lucas', 17], ['Lucas', 17], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9],['John', 8], ['John', 8], ['Lucas', 17],['Marcus', 8], ['Marcus', 8], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9],['Marcus', 8], ['Marcus', 8], ['Beto', 17], ['Beto', 17], ['Beto', 17], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9],['Marcus', 8], ['Marcus', 8], ['Beto', 17], ['John', 8], ['John', 8], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9],['John', 8], ['John', 8], ['Lucas', 17], ['Lucas', 17], ['Lucas', 17], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['John', 8], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9], ['Mary', 7], ['Mary', 7], ['Mike', 9], ['Mike', 9],['John', 8], ['John', 8], ['Lucas', 17],['Marcus', 8], ['Marcus', 8], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9],['Marcus', 8], ['Marcus', 8], ['Beto', 17], ['Beto', 17], ['Beto', 17], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9], ['Beatriz', 14], ['Beatriz', 14], ['Gabriela', 14], ['Gabriela', 14], ['Marcus', 8], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9], ['Maricotas', 7], ['Maricotas', 7], ['Merlin', 9], ['Merlin', 9],['Marcus', 8], ['Marcus', 8], ['Beto', 17]]
mylen=len(mylist)
print('Old list has:' + str(mylen))
print(mylist)
data_md5 = hashlib.md5(json.dumps(mylist, sort_keys=True).encode('utf-8')).hexdigest()
print(data_md5)
previtem=['','']
endlist=[]
while mylen > 1:
    myrand=random.randrange(0, mylen-1)
    selected=mylist[myrand]
    if selected!=previtem:
        tmpitem=mylist.pop(myrand)
        mylen=len(mylist)
        endlist.append(selected)
        previtem=selected
print('-----')
print('--Looking where to insert last item--')
for i in range(1,len(endlist)):
    if (endlist[i-1]!=mylist) and (endlist[i]!=mylist):
        break
endlist.insert(i, mylist)
print('New list has:' + str(len(endlist)))
print(endlist)
data_md5 = hashlib.md5(json.dumps(endlist, sort_keys=True).encode('utf-8')).hexdigest()
print(data_md5)

Example of running this script with results

Upvotes: 1

Andrej Kesely
Andrej Kesely

Reputation: 195573

Another solution (to get random results). Crate a temporary dictionary where keys are names and values ale lists of values from original data.

Select one element at random (which has most values) and put it as first element in output list, then select at pop at random from lists which have the most values left.

from random import choice

lst = [
    ["John", 8],
    ["John", 8],
    ["John", 8],
    ["Mary", 7],
    ["Mary", 7],
    ["Mike", 9],
    ["Mike", 9],
]

def get_random_max(d):
    m = max(map(len, d.values()))
    return choice([[k, v] for k, v in d.items() if len(v) == m])

tmp = {}
for name, value in lst:
    tmp.setdefault(name, []).append(value)

k, v = get_random_max(tmp)
out = [[k, v.pop()]]

while any(tmp.values()):
    k, v = get_random_max({k: v for k, v in tmp.items() if k != out[-1][0]})
    out.append([k, v.pop()])

print(out)

Prints (for example):

[['John', 8], ['Mary', 7], ['Mike', 9], ['John', 8], ['Mike', 9], ['John', 8], ['Mary', 7]]

EDIT: Incorporated the suggestions from @KellyBundy. Thanks!

Upvotes: 3

Related Questions