[2.5.1.1/dictionary] Change sorting order?

Dave Angel davea at ieee.org
Fri Jan 22 11:54:58 EST 2010


Gilles Ganault wrote:
> On Fri, 22 Jan 2010 09:49:32 -0500, Dave Angel <davea at ieee.org> wrote:
>   
>> Seems to me the other solutions I've seen so far are more complex than 
>> needed.  I figure you either want an unordered list, in which case you 
>> could use random.shuffle(), or you want a list that's sorted, but starts 
>> somewhere in the middle, at an arbitrary place, goes to the end, and 
>> wraps back to the beginning.  So use random.randint() to choose an index 
>> within the list, and concatenate two slices of the list, based on that 
>> index in reverse order.
>>     
>
> Yes, this is exactly what I need: Start listing items from a given
> index (actually, using a character since the list contains names) all
> the way to the end of the list; If the character wasn't the very
> first, go back to the first time and display the list until we get to
> the current character.
>
> Python is so feature-rich, I'm sure there's a much simpler way to do
> this than this crappy code of mine:
>
> =============
> connected = []
> connected.append("0dummy")
> connected.append("aa")
> connected.append("bb")
> connected.append("cc")
>
> index = 0
> for item in connected:
> 	#For testing purposes;
> 	#Final code will read/increment character from file
> 	if item[index] == "b":
> 		break
> 	else:
> 		index = index + 1
>
> #Print items between current character and end of list
> tempindex = index
> while(tempindex < len(connected)):
> 	print connected[tempindex]
> 	tempindex = tempindex + 1
>
> #if current letter not first character,
> #display beginning of list up to current character
> if index != 0:
> 	tempindex = 0
> 	while tempindex < index:
> 		print connected[tempindex]
> 		tempindex = tempindex + 1
> =============
>
> Thank you for any help
>
>   
Your code would fail if you picked a letter for which there were no 
entries.  That's easily fixed,  just use >=  instead of == in your if test.

Jean-Michel Pichavant  post implements my second option.  So I'll borrow 
his code here.
 
But apparently you want my third option:  random starting place, but 
with all the names starting with the same character together.  To get 
that, but with the distribution proportional to the number of names that 
start with the given character, you need to get the index in two 
stages.  First use the random.randint().  Then do a search for the first 
name that starts with that same character.  For that, I borrow from 
Duncan Booth, and use bisect.bisect().

import random, bisect

connected = sorted( ['jj', '0test', '3test', 'aa', 'aj', 'bb', 'bz', 
'dc', 'df'] )

def getNewOrder(myList):
    index = random.randint(0,len(myList)-1)
    startch = myList[index][0]
    pos = bisect.bisect_left(myList, startch)
    print index, myList[index], pos, myList[pos]
    return myList[pos:] + myList[:pos] # using slicing instead of list 
comprehension (suggested by DaveA)

print connected
for i in range(6):
    print getNewOrder(connected)

I have the extra print inside the function to show (for example) that if 
'aj' is picked, it actually will start with'aa'

Note that with your constraints, there's no way it can be fair.  But 
experiment a bit, and see if it meets your needs.

DaveA




More information about the Python-list mailing list