Sorting a multidimensional array by multiple keys

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rehceb Rotkiv

    #1

    Sorting a multidimensional array by multiple keys

    Hello everyone,

    can I sort a multidimensiona l array in Python by multiple sort keys? A
    litte code sample would be nice!

    Thx,
    Rehceb

  • =?UTF-8?B?VGhvbWFzIEtyw7xnZXI=?=

    #2
    Re: Sorting a multidimensiona l array by multiple keys

    Rehceb Rotkiv schrieb:
    can I sort a multidimensiona l array in Python by multiple sort keys? A
    litte code sample would be nice!
    You can pass a function as argument to the sort method of a list.
    The function should take two arguments and return -1, 0 or 1 as
    comparison result. Just like the cmp function.

    This will objects in list obj_lst by their id attributes:

    def sorter(a, b):
    return cmp(a.id, b.id)

    obj_lst.sort(so rter)

    Thomas

    Comment

    • bearophileHUGS@lycos.com

      #3
      Re: Sorting a multidimensiona l array by multiple keys

      Rehceb Rotkiv:
      can I sort a multidimensiona l array in Python by multiple sort keys? A
      litte code sample would be nice!
      If you want a good answer you have to give me/us more details, and an
      example too.

      Bye,
      bearophile

      Comment

      • Rehceb Rotkiv

        #4
        Re: Sorting a multidimensiona l array by multiple keys

        If you want a good answer you have to give me/us more details, and an
        example too.
        OK, here is some example data:

        reaction is BUT by the
        sodium , BUT it is
        sea , BUT it is
        this manner BUT the dissolved
        pattern , BUT it is
        rapid , BUT it is

        As each line consists of 5 words, I would break up the data into an array
        of five-field-arrays (Would you use lists or tuples or a combination in
        Python?). The word "BUT" would be in the middle, with two fields/words
        left and two fields/words right of it. I then want to sort this list by

        - field 3
        - field 4
        - field 1
        - field 0

        in this hierarchy. This is the desired result:

        pattern , BUT it is
        rapid , BUT it is
        sea , BUT it is
        sodium , BUT it is
        reaction is BUT by the
        this manner BUT the dissolved

        The first 4 lines all could not be sorted by fields 3 & 4, as they are
        identical ("it", "is"), so they have been sorted first by field 1 (which
        is also identical: ",") and then by field 0:

        pattern
        rapid
        sea
        sodium

        I hope I have explained this in an understandable way. It would be cool
        if you could show me how this can be done in Python!

        Regards,
        Rehceb

        Comment

        • Rehceb Rotkiv

          #5
          Re: Sorting a multidimensiona l array by multiple keys

          Wait, I made a mistake. The correct result would be

          reaction is BUT by the
          pattern , BUT it is
          rapid , BUT it is
          sea , BUT it is
          sodium , BUT it is
          this manner BUT the dissolved

          because "by the" comes before and "the dissolved" after "it is". Sorry
          for the confusion.

          Comment

          • Steven Bethard

            #6
            Re: Sorting a multidimensiona l array by multiple keys

            Rehceb Rotkiv wrote:
            >If you want a good answer you have to give me/us more details, and an
            >example too.
            >
            OK, here is some example data:
            >
            reaction is BUT by the
            sodium , BUT it is
            sea , BUT it is
            this manner BUT the dissolved
            pattern , BUT it is
            rapid , BUT it is
            >
            As each line consists of 5 words, I would break up the data into an array
            of five-field-arrays (Would you use lists or tuples or a combination in
            Python?). The word "BUT" would be in the middle, with two fields/words
            left and two fields/words right of it. I then want to sort this list by
            >
            - field 3
            - field 4
            - field 1
            - field 0
            You're probably looking for the key= argument to list.sort(). If your
            function simply returns the fields in the order above, I believe you get
            the right thing::
            >>s = '''\
            .... reaction is BUT by the
            .... sodium , BUT it is
            .... sea , BUT it is
            .... this manner BUT the dissolved
            .... pattern , BUT it is
            .... rapid , BUT it is
            .... '''
            >>word_lists = [line.split() for line in s.splitlines()]
            >>def key(word_list):
            .... return word_list[3], word_list[4], word_list[1], word_list[0]
            ....
            >>word_lists.so rt(key=key)
            >>word_lists
            [['reaction', 'is', 'BUT', 'by', 'the'],
            ['pattern', ',', 'BUT', 'it', 'is'],
            ['rapid', ',', 'BUT', 'it', 'is'],
            ['sea', ',', 'BUT', 'it', 'is'],
            ['sodium', ',', 'BUT', 'it', 'is'],
            ['this', 'manner', 'BUT', 'the', 'dissolved']]

            STeVe

            Comment

            • Duncan Booth

              #7
              Re: Sorting a multidimensiona l array by multiple keys

              Rehceb Rotkiv <rehceb@no.spam .plzwrote:
              Wait, I made a mistake. The correct result would be
              >
              reaction is BUT by the
              pattern , BUT it is
              rapid , BUT it is
              sea , BUT it is
              sodium , BUT it is
              this manner BUT the dissolved
              >
              because "by the" comes before and "the dissolved" after "it is". Sorry
              for the confusion.
              >>data = [
              "reaction is BUT by the",
              "sodium , BUT it is",
              "sea , BUT it is",
              "this manner BUT the dissolved",
              "pattern , BUT it is",
              "rapid , BUT it is",
              ]
              >>data = [ s.split() for s in data]
              >>from pprint import pprint
              >>pprint(data )
              [['reaction', 'is', 'BUT', 'by', 'the'],
              ['sodium', ',', 'BUT', 'it', 'is'],
              ['sea', ',', 'BUT', 'it', 'is'],
              ['this', 'manner', 'BUT', 'the', 'dissolved'],
              ['pattern', ',', 'BUT', 'it', 'is'],
              ['rapid', ',', 'BUT', 'it', 'is']]
              >>from operator import itemgetter
              >>data.sort(key =itemgetter(0))
              >>data.sort(key =itemgetter(1))
              >>data.sort(key =itemgetter(4))
              >>data.sort(key =itemgetter(3))
              >>pprint(data )
              [['reaction', 'is', 'BUT', 'by', 'the'],
              ['pattern', ',', 'BUT', 'it', 'is'],
              ['rapid', ',', 'BUT', 'it', 'is'],
              ['sea', ',', 'BUT', 'it', 'is'],
              ['sodium', ',', 'BUT', 'it', 'is'],
              ['this', 'manner', 'BUT', 'the', 'dissolved']]

              Comment

              • attn.steven.kuo@gmail.com

                #8
                Re: Sorting a multidimensiona l array by multiple keys

                On Mar 31, 6:42 am, Rehceb Rotkiv <reh...@no.spam .plzwrote:

                (snipped)
                As each line consists of 5 words, I would break up the data into an array
                of five-field-arrays (Would you use lists or tuples or a combination in
                Python?). The word "BUT" would be in the middle, with two fields/words
                left and two fields/words right of it. I then want to sort this list by
                >
                - field 3
                - field 4
                - field 1
                - field 0


                import StringIO

                buf = """
                reaction is BUT by the
                sodium , BUT it is
                sea , BUT it is
                this manner BUT the dissolved
                pattern , BUT it is
                rapid , BUT it is
                """.lstrip( )

                mockfile = StringIO.String IO(buf)

                tokens = [ line.split() + [ line ] for line in mockfile ]
                tokens.sort(key =lambda l: (l[3], l[4], l[1], l[0]))
                for l in tokens:
                print l[-1],


                --
                Hope this helps,
                Steven

                Comment

                • Peter Otten

                  #9
                  Re: Sorting a multidimensiona l array by multiple keys

                  Duncan Booth wrote:
                  >>>from operator import itemgetter
                  >>>data.sort(ke y=itemgetter(0) )
                  >>>data.sort(ke y=itemgetter(1) )
                  >>>data.sort(ke y=itemgetter(4) )
                  >>>data.sort(ke y=itemgetter(3) )
                  Or, in Python 2.5:
                  >>data.sort(key =itemgetter(3, 4, 1, 0))
                  Peter

                  Comment

                  • Rehceb Rotkiv

                    #10
                    Re: Sorting a multidimensiona l array by multiple keys

                    Thank you all for your helpful solutions!

                    Regards,
                    Rehceb

                    Comment

                    • Duncan Booth

                      #11
                      Re: Sorting a multidimensiona l array by multiple keys

                      Peter Otten <__peter__@web. dewrote:
                      Duncan Booth wrote:
                      >
                      >>>>from operator import itemgetter
                      >>>>data.sort(k ey=itemgetter(0 ))
                      >>>>data.sort(k ey=itemgetter(1 ))
                      >>>>data.sort(k ey=itemgetter(4 ))
                      >>>>data.sort(k ey=itemgetter(3 ))
                      >
                      Or, in Python 2.5:
                      >
                      >>>data.sort(ke y=itemgetter(3, 4, 1, 0))
                      >
                      Thanks, I'd forgotten itemgetter had that strangley assymmetric behaviour
                      of returning either a single value or a tuple.

                      Comment

                      • Paulo da Silva

                        #12
                        Re: Sorting a multidimensiona l array by multiple keys

                        Rehceb Rotkiv escreveu:
                        Hello everyone,
                        >
                        can I sort a multidimensiona l array in Python by multiple sort keys? A
                        litte code sample would be nice!
                        class MyList(list):
                        # This is the index of the element to be compared
                        CmpIndex=0

                        # Comparision methods
                        @staticmethod
                        def __cmp_pars(x,y) :
                        if isinstance(x,My List):
                        x=x[MyList.CmpIndex]
                        if isinstance(y,My List):
                        y=y[MyList.CmpIndex]
                        return x,y
                        def __cmp__(self,ot her):
                        s,o=MyList.__cm p_pars(self,oth er)
                        return cmp(s,o)
                        def __lt__(self,oth er):
                        s,o=MyList.__cm p_pars(self,oth er)
                        return s<o
                        def __le__(self,oth er):
                        s,o=MyList.__cm p_pars(self,oth er)
                        return s<=o
                        def __gt__(self,oth er):
                        s,o=MyList.__cm p_pars(self,oth er)
                        return s>o
                        def __ge__(self,oth er):
                        s,o=MyList.__cm p_pars(self,oth er)
                        return s>=o
                        def __eq__(self,oth er):
                        s,o=MyList.__cm p_pars(self,oth er)
                        return s==o
                        def __ne__(self,oth er):
                        s,o=MyList.__cm p_pars(self,oth er)
                        return s!=o

                        Use:

                        x=MyList(<list of lists>)
                        MyList.CmpIndex =2 # Compare by index 2
                        x.sort()

                        May be there is a better solution ...
                        HTH
                        Paulo

                        Comment

                        • Alex Martelli

                          #13
                          Re: Sorting a multidimensiona l array by multiple keys

                          Thomas Krüger <newsgroups@nos pam.nowire.orgw rote:
                          Rehceb Rotkiv schrieb:
                          can I sort a multidimensiona l array in Python by multiple sort keys? A
                          litte code sample would be nice!
                          >
                          You can pass a function as argument to the sort method of a list.
                          The function should take two arguments and return -1, 0 or 1 as
                          comparison result. Just like the cmp function.
                          >
                          This will objects in list obj_lst by their id attributes:
                          >
                          def sorter(a, b):
                          return cmp(a.id, b.id)
                          >
                          obj_lst.sort(so rter)
                          A MUCH better way to obtain exactly the same semantics would be:

                          def getid(a):
                          return a.id

                          obj_list.sort(k ey=getid)


                          Alex

                          Comment

                          • =?ISO-8859-1?Q?Thomas_Kr=FCger?=

                            #14
                            Re: Sorting a multidimensiona l array by multiple keys

                            Alex Martelli schrieb:
                            Thomas Krüger <newsgroups@nos pam.nowire.orgw rote:
                            >def sorter(a, b):
                            > return cmp(a.id, b.id)
                            >>
                            >obj_lst.sort(s orter)
                            >
                            A MUCH better way to obtain exactly the same semantics would be:
                            >
                            def getid(a):
                            return a.id
                            >
                            obj_list.sort(k ey=getid)
                            Frankly speaking the purpose of the example was to show how to pass a
                            function as argument for the sort method.
                            Your code may be more efficient but it explains something different.

                            Thomas

                            Comment

                            • Steven Bethard

                              #15
                              Re: Sorting a multidimensiona l array by multiple keys

                              Thomas Krüger wrote:
                              Alex Martelli schrieb:
                              >Thomas Krüger <newsgroups@nos pam.nowire.orgw rote:
                              >>def sorter(a, b):
                              >> return cmp(a.id, b.id)
                              >>>
                              >>obj_lst.sort( sorter)
                              >A MUCH better way to obtain exactly the same semantics would be:
                              >>
                              >def getid(a):
                              > return a.id
                              >>
                              >obj_list.sort( key=getid)
                              >
                              Frankly speaking the purpose of the example was to show how to pass a
                              function as argument for the sort method.
                              Your code may be more efficient but it explains something different.
                              Yes, but there's almost never a reason to use the cmp= argument to
                              sort() anymore. It's almost always better to use the key= argument.

                              STeVe

                              Comment

                              Working...