Sorting a list depending of the indexes of another sorted list

Discussion in 'Python' started by Santiago Romero, Jan 21, 2008.

  1. 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.
     
    Santiago Romero, Jan 21, 2008
    #1
    1. Advertising

  2. Santiago  Romero

    babui Guest

    On 21 ene, 08:41, Santiago Romero <> wrote:
    > 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
    > Thanks.
     
    babui, Jan 21, 2008
    #2
    1. Advertising

  3. Santiago  Romero

    J. Peng Guest

    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 写é“:
    > 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"]
    >
     
    J. Peng, Jan 21, 2008
    #3
  4. Santiago  Romero

    J. Peng Guest

    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]
     
    J. Peng, Jan 21, 2008
    #4
  5. Santiago  Romero

    Peter Otten Guest

    Santiago Romero wrote:

    > 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
     
    Peter Otten, Jan 21, 2008
    #5
  6. On Mon, 21 Jan 2008 16:23:50 +0800, J. Peng wrote:

    > 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]


    --
    Steven
     
    Steven D'Aprano, Jan 21, 2008
    #6
  7. Santiago  Romero

    J. Peng Guest

    Steven D'Aprano 写é“:
    > On Mon, 21 Jan 2008 16:23:50 +0800, J. Peng wrote:
    >
    >> 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?
     
    J. Peng, Jan 21, 2008
    #7
  8. 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
     
    Santiago Romero, Jan 21, 2008
    #8
  9. On Mon, 21 Jan 2008 17:32:42 +0800, J. Peng wrote:

    > Steven D'Aprano 写é“:
    >> On Mon, 21 Jan 2008 16:23:50 +0800, J. Peng wrote:
    >>
    >>> 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"



    --
    Steven
     
    Steven D'Aprano, Jan 21, 2008
    #9
  10. On Mon, 21 Jan 2008 09:53:10 +0100, Peter Otten wrote:

    > Santiago Romero wrote:
    >
    >> 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']



    --
    Steven
     
    Steven D'Aprano, Jan 21, 2008
    #10
  11. Santiago  Romero

    Peter Otten Guest

    Steven D'Aprano wrote:

    >> 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:

    >>> def dsu(items, key, reorder=lambda x: x):

    .... 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
     
    Peter Otten, Jan 21, 2008
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. William Payne
    Replies:
    2
    Views:
    1,530
    William Payne
    Apr 20, 2004
  2. custard_pie
    Replies:
    10
    Views:
    758
    Scott David Daniels
    May 3, 2005
  3. Glenn Linderman

    Sorted indexes in Python

    Glenn Linderman, Oct 17, 2008, in forum: Python
    Replies:
    0
    Views:
    608
    Glenn Linderman
    Oct 17, 2008
  4. Toto
    Replies:
    6
    Views:
    269
    Andreas Waldenburger
    Sep 29, 2010
  5. Replies:
    5
    Views:
    118
Loading...

Share This Page