where or filter on list

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • charles.hebert@gmail.com

    #1

    where or filter on list

    Hi,

    Can anybody tell me how to to find the nearest value to zero in a list
    ?

    To do that, i'm using list comprenhension :
    >>foo = [-5,-1,2,3] # nearest value to zero ?
    >>[value for value in foo if math.fabs(value ) == min([int(math.fabs(x )) for x in foo])]
    [-1]

    Something simpler ?
    How to extend this function to any given value ?

    Thanks,

    CH.

  • skip@pobox.com

    #2
    Re: where or filter on list

    >>>foo = [-5,-1,2,3] # nearest value to zero ?
    >>>[value for value in foo if math.fabs(value ) == min([int(math.fabs(x )) for x in foo])]
    charles[-1]

    charlesSomethin g simpler ?

    Well, you can just use the abs() builtin instead of math.fabs. Also, just
    compute the min/abs once:

    minval = min([int(math.fabs(x )) for x in foo])
    [value for value in foo if fabs(value) == minval]

    Another way might be to sort by absolute value:

    intermed = [(abs(v), v) for v in foo]
    intermed.sort()
    intermed[0][1]

    That only gives you one of possibly many values closest to zero.

    charlesHow to extend this function to any given value ?

    Just subtract that value from all values in the list:

    intermed = [(abs(v-x), v) for v in foo]
    intermed.sort()
    intermed[0][1]

    Skip

    Comment

    • Duncan Booth

      #3
      Re: where or filter on list

      skip@pobox.com wrote:
      Another way might be to sort by absolute value:
      >
      intermed = [(abs(v), v) for v in foo]
      intermed.sort()
      intermed[0][1]
      It is slightly simpler if you use sorted (assuming a recent enough Python):

      intermed = sorted(foo, key=abs)
      print intermed[0]

      The sorted list is of course the best way if you want to find not just one
      value but a group, e.g. the n nearest to 0.

      For nearest to a non-zero value v the version with sorted becomes:

      intermed = sorted(foo, key=lambda x:abs(x-v))

      Comment

      • Philipp Pagel

        #4
        Re: where or filter on list

        charles.hebert@ gmail.com <charles.hebert @gmail.comwrote :
        Can anybody tell me how to to find the nearest value to zero in a
        list?
        >foo = [-5,-1,2,3] # nearest value to zero ?
        >[value for value in foo if math.fabs(value ) == min([int(math.fabs(x )) for x in foo])]
        [-1]
        Something simpler ?
        Maybe something like this:

        mindist = min(map(abs, foo))
        filter(lambda x: abs(x) == mindist, a)[0]

        Only annoyance: we compute abs twice for each value. We could probably
        avoid that by using reduce() and a suitable function...
        How to extend this function to any given value ?
        By subtracting the desired value from foo.

        cu
        Philipp

        --
        Dr. Philipp Pagel Tel. +49-8161-71 2131
        Dept. of Genome Oriented Bioinformatics Fax. +49-8161-71 2186
        Technical University of Munich

        Comment

        • Larry Bates

          #5
          Re: where or filter on list

          charles.hebert@ gmail.com wrote:
          Hi,
          >
          Can anybody tell me how to to find the nearest value to zero in a list
          ?
          >
          To do that, i'm using list comprenhension :
          >
          >>>foo = [-5,-1,2,3] # nearest value to zero ?
          >>>[value for value in foo if math.fabs(value ) == min([int(math.fabs(x )) for x in foo])]
          [-1]
          >
          Something simpler ?
          How to extend this function to any given value ?
          >
          Thanks,
          >
          CH.
          >
          One of I'm sure many ways:

          import sys
          def closest(value, list):
          m=None
          mdistance=sys.m axint
          for entry in list:
          distance=abs(va lue-entry)
          if distance < mdistance:
          m=entry
          mdistance=dista nce
          return m

          if __name__ == "__main__":
          foo = [-5,-1,2,3]
          print closest(0, foo)

          Note: If you know that the list is ordered you can break out of the
          loop you can optimize the loop by breaking out when you start getting
          further away from value or you might be able to use the bisect module
          to find it faster. If the lists are small it probably isn't worth
          the extra effort. If they are large and sorted look at bisect.

          Question: what if two values are equidistant?

          -Larry bATES

          Comment

          • charles.hebert@gmail.com

            #6
            Re: where or filter on list

            Thanks all !
            Question: what if two values are equidistant?
            >>def closest(foo,v):
            .... intermed = [(abs(v), v) for v in foo]
            .... intermed.sort()
            .... return [x[1] for x in intermed if x[0] == intermed[0][0]]
            ....
            >>print closest([-20,-10,10,15],0)
            [-10, 10]

            Works fine !

            (now with sorted ... ?)

            Comment

            • skip@pobox.com

              #7
              Re: where or filter on list

              >Another way might be to sort by absolute value:
              >>
              >intermed = [(abs(v), v) for v in foo]
              >intermed.sort( )
              >intermed[0][1]
              DuncanIt is slightly simpler if you use sorted (assuming a recent
              Duncanenough Python):

              Duncan intermed = sorted(foo, key=abs)
              Duncan print intermed[0]

              Yeah, sorted() is new enough that my brain generally doesn't realize it's
              available. I also never remember the key parameter to list.sort(). Now
              that you mention it:
              >>foo = [5, 2, -1, -7, 3, -6, 2, 12]
              >>foo.sort(key= abs)
              >>foo
              [-1, 2, 2, 3, 5, -6, -7, 12]

              (assuming you don't mind reording the list - if you do, then sorted() is
              your friend).

              Skip

              Comment

              • Neil Cerutti

                #8
                Re: where or filter on list

                On 2006-08-30, charles.hebert@ gmail.com <charles.hebert @gmail.comwrote :
                Hi,
                >
                Can anybody tell me how to to find the nearest value to zero in a list
                ?
                >
                To do that, i'm using list comprenhension :
                >
                >>>foo = [-5,-1,2,3] # nearest value to zero ?
                >>>[value for value in foo if math.fabs(value ) == min([int(math.fabs(x )) for x in foo])]
                [-1]
                >
                Something simpler ?
                How to extend this function to any given value ?
                A hand-crafted loop seems like an efficient solution:

                def closest_to(n, seq):
                m = 0
                for i in xrange(1, len(seq)):
                if abs(n-seq[i]) < abs(n-seq[m]):
                m = i
                return seq[m]

                Putting my faith in Python builtins instead:

                def closest_to(n, seq):
                s = [abs(n-x) for x in seq]
                return seq[s.index(min(s))]

                --
                Neil Cerutti

                Comment

                • Duncan Booth

                  #9
                  Re: where or filter on list

                  skip@pobox.com wrote:
                  >
                  >Another way might be to sort by absolute value:
                  >>
                  >intermed = [(abs(v), v) for v in foo]
                  >intermed.sort( )
                  >intermed[0][1]
                  >
                  DuncanIt is slightly simpler if you use sorted (assuming a recent
                  Duncanenough Python):
                  >
                  Duncan intermed = sorted(foo, key=abs)
                  Duncan print intermed[0]
                  >
                  Yeah, sorted() is new enough that my brain generally doesn't realize it's
                  available. I also never remember the key parameter to list.sort().
                  You're not the only one who has trouble remembering just what is in each
                  version.
                  Now that you mention it:
                  >
                  >>foo = [5, 2, -1, -7, 3, -6, 2, 12]
                  >>foo.sort(key= abs)
                  >>foo
                  [-1, 2, 2, 3, 5, -6, -7, 12]
                  >
                  (assuming you don't mind reording the list - if you do, then sorted() is
                  your friend).
                  And for Python 2.5 users only we have the exciting new option of:
                  >>foo = [5, 2, -1, -7, 3, -6, 2, 12]
                  >>min(foo, key=abs)
                  -1

                  Comment

                  • bearophileHUGS@lycos.com

                    #10
                    Re: where or filter on list

                    Duncan Booth:
                    And for Python 2.5 users only we have the exciting new option of:
                    >foo = [5, 2, -1, -7, 3, -6, 2, 12]
                    >min(foo, key=abs)
                    -1
                    Good. This is possibility for older Python:

                    l = [(rnd()-0.5) * 20 for i in xrange(1000)]
                    print min( (abs(el), el) for el in l )[1]

                    Bye,
                    bearophile

                    Comment

                    • Larry Bates

                      #11
                      Re: where or filter on list

                      What I mean is: What if there are two items that are
                      equidistant to what you are searching for?


                      Example:

                      foo = [-5,-1,1,3,5]
                      print closest(0, foo)

                      -1 and 1 are both "equally close" to zero that I'm
                      searching for. This is an edge case that you didn't
                      define an answer to and closest function that I
                      wrote may (or may not) return the correct answer.

                      -Larry

                      charles.hebert@ gmail.com wrote:
                      Thanks all !
                      >
                      >Question: what if two values are equidistant?
                      >
                      >>>def closest(foo,v):
                      ... intermed = [(abs(v), v) for v in foo]
                      ... intermed.sort()
                      ... return [x[1] for x in intermed if x[0] == intermed[0][0]]
                      ...
                      >>>print closest([-20,-10,10,15],0)
                      [-10, 10]
                      >
                      Works fine !
                      >
                      (now with sorted ... ?)
                      >

                      Comment

                      Working...