Sorting a list depending of the indexes of another sorted list

S

Santiago Romero

Hi ...

I have the following DNS MX records info:

domain.com
preference 10 host mx1.domain.com
preference 30 host anotherhost.domain.com
preference 20 host mx2.domain.com

I'm storing this info in 2 lists:

preferences = [10, 30, 20]
hosts = [ "mx1.domain.com", "anotherhost.domain.com",
"mx2.domain.com"]

(I was about to use a dict of preferences : domain, but it's
possible to find 2 mx records with the same preference, so keys
wouldnt be unique).

I'm trying to sort both lists so that they end like this:

preferences = [10, 20, 30]
hosts = [ "mx1.domain.com", "mx2.domain.com",
"anotherhost.domain.com" ]

I want to sort hosts list depending on the numeric order of
"preferences".


And finally ... do you think there is a better python structure to
store this data and sort it in a more easy way?

Thanks.
 
B

babui

Hi ...

I have the following DNS MX records info:

domain.com
preference 10 host mx1.domain.com
preference 30 host anotherhost.domain.com
preference 20 host mx2.domain.com
And finally ... do you think there is a better python structure to
store this data and sort it in a more easy way?

Why don't you use a list of tuples?

L = [ (10, "mx1.domain.com"), (30, "anotherhost.domain.com", (20,
"mx2.domain.com") ]

and L.sort() sorts the list !!!

Juan M. Gimeno
 
J

J. Peng

I tried to write it below,it can work,:)

v= """preference 10 host mx1.domain.com
preference 30 host anotherhost.domain.com
preference 20 host mx2.domain.com"""

x=v.split("\n")

li =[]
for i in x:
k = (i.split())[3]
y = (i.split())[1]
li.append((y,k))

li.sort()
print li


the output is:
[('10', 'mx1.domain.com'), ('20', 'mx2.domain.com'), ('30',
'anotherhost.domain.com')]



Santiago Romero 写é“:
 
P

Peter Otten

Santiago said:
I'm trying to sort both lists so that they end like this:

preferences = [10, 20, 30]
hosts = [ "mx1.domain.com", "mx2.domain.com",
"anotherhost.domain.com" ]

I want to sort hosts list depending on the numeric order of
"preferences".

The following relies on undocumented (I hope) behaviour:
preferences = [10, 30, 20]
hosts = [ "mx1.domain.com", "anotherhost.domain.com", "mx2.domain.com"]
hosts.sort(key=lambda x, p=iter(preferences).next: p())
preferences.sort()
hosts ['mx1.domain.com', 'mx2.domain.com', 'anotherhost.domain.com']
preferences
[10, 20, 30]

Don't do it, use a list of tuples as already suggested.

Peter
 
S

Steven D'Aprano

J. Peng 写é“:
k = (i.split())[3]
y = (i.split())[1]

btw, why can't I write the above two into one statement?

(k,y) = (i.split())[3,1]

I don't know. What's "i"?

I'm guessing "i" is a string (and what a horrible choice of a name for a
string!) So i.split() will return a list. List indexing with multiple
arguments isn't defined, which is why you can't write

k, y = (i.split())[3,1]


BTW, the outermost set of brackets is unnecessary. You can write:

i.split()[3]

instead of (i.split())[3]
 
J

J. Peng

Steven D'Aprano 写é“:
J. Peng 写é“:
k = (i.split())[3]
y = (i.split())[1]
btw, why can't I write the above two into one statement?

(k,y) = (i.split())[3,1]

I don't know. What's "i"?

I'm guessing "i" is a string (and what a horrible choice of a name for a
string!) So i.split() will return a list. List indexing with multiple
arguments isn't defined, which is why you can't write

k, y = (i.split())[3,1]

Thanks.
Then one have to split the list twice.Given the list is large,it's maybe
not good for performance.Is it a more effective split way?
 
S

Santiago Romero

Thanks all for the answers ... I'll use a tuple as you said :)

Anyway, is interesting to know how to sort 2 lists when you dont want
to use tuples, so thanks also to Peter :)
Then one have to split the list twice.Given the list is large,it's maybe
not good for performance.Is it a more effective split way?

Well, I just use:

rows = i.split(' ')
a = rows[3]
b = rows[5]

X-D
 
S

Steven D'Aprano

Steven D'Aprano 写é“:
J. Peng 写é“:

k = (i.split())[3]
y = (i.split())[1]
btw, why can't I write the above two into one statement?

(k,y) = (i.split())[3,1]

I don't know. What's "i"?

I'm guessing "i" is a string (and what a horrible choice of a name for
a string!) So i.split() will return a list. List indexing with multiple
arguments isn't defined, which is why you can't write

k, y = (i.split())[3,1]
Thanks.
Then one have to split the list twice.Given the list is large,it's maybe
not good for performance.Is it a more effective split way?

Yes, split the string once and store it.

words = "Nobody expects the Spanish Inquisition!"
alist = words.split()
k = alist[3] # "Spanish"
y = alist[1] # "expects"
 
S

Steven D'Aprano

Santiago said:
I'm trying to sort both lists so that they end like this:

preferences = [10, 20, 30]
hosts = [ "mx1.domain.com", "mx2.domain.com", "anotherhost.domain.com"
]

I want to sort hosts list depending on the numeric order of
"preferences".

The following relies on undocumented (I hope) behaviour:


What bit are you suggesting is undocumented?

preferences = [10, 30, 20]
hosts = [ "mx1.domain.com", "anotherhost.domain.com", ... "mx2.domain.com"]
hosts.sort(key=lambda x, p=iter(preferences).next: p())
preferences.sort()
hosts ['mx1.domain.com', 'mx2.domain.com', 'anotherhost.domain.com']
preferences
[10, 20, 30]

Now if you wanted to claim it was opaque and confusing, I'd agree with
you :)


Here's a function that uses the Decorate-Sort-Undecorate technique to
sort one list by the contents of another:



from sys import maxint
_indices = xrange(maxint)

def sorterDSU(alist, blist):
"""Return a copy of alist sorted by the contents of blist."""
assert len(alist) == len(blist)
decorated = zip(blist, _indices, alist)
decorated.sort()
return [avalue for (bvalue, i, avalue) in decorated]



Here's another version:

def sorter(alist, blist):
assert len(alist) == len(blist)
table = sorted(range(len(alist)), key=blist.__getitem__)
return [alist for i in table]


alist = "John Eric Michael Graham Terry-J Terry-G".split()
blist = [5, 0, 4, 1, 3, 2]
sorter(alist, blist)
['Eric', 'Graham', 'Terry-G', 'Terry-J', 'Michael', 'John']
 
P

Peter Otten

Steven said:
The following relies on undocumented (I hope) behaviour:
preferences = [10, 30, 20]
hosts = [ "mx1.domain.com", "anotherhost.domain.com", ... "mx2.domain.com"]
hosts.sort(key=lambda x, p=iter(preferences).next: p())
preferences.sort()
hosts
['mx1.domain.com', 'mx2.domain.com', 'anotherhost.domain.com']
What bit are you suggesting is undocumented?

The lambda spits out the items in preferences in the same order as they
occur in that list. If hosts.sort(key=...) in its C-implemented decoration
phase would iterate over the items in hosts in, say, reverse order hosts
would not be sorted correctly. Here's an illustration in Python:
.... for i in reorder(range(len(items))):
.... items = key(items), items
.... items.sort()
.... items[:] = [v for k, v in items]
.... return items
....
dsu([1,2,3], lambda x, n=iter("acb").next: n()) [1, 3, 2]
dsu([1,2,3], lambda x, n=iter("acb").next: n(), reversed)
[3, 1, 2]

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top