disgrating a list

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Simon Forman

    #16
    Re: disgrating a list

    jwaixs wrote:
    Thank you for all your reply and support. Neil's fits the most to me. I
    shrinked it to this function:
    >
    def flatten(x):
    for i in range(len(x)):
    if isinstance(x[i], list):
    x[i:i+1] = x[i]
    >
    Thank you all again. If someone could find even a cuter way, I'd like
    to see that way.
    >
    Noud Aldenhoven
    That version's broken, but this version works (but only with lists, of
    course):

    def flatten(x):
    i, length = 0, len(x)
    while i < length:
    n = x[i]
    if isinstance(n, list):
    x[i:i+1] = n
    length += len(n) - 1
    else:
    i += 1

    x = [1, [2, 3, [[]], 4], [[5, 6, 7], [], 8, [9]], 10, [11]]
    flatten(x)
    print x


    Prints:
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]


    You can't increment the index until you're sure you're x[i] isn't a
    list, and you have to keep track of the length of x as you go (that's
    why your for loop is broken.)

    Peace,

    Comment

    • Tal Einat

      #17
      Re: disgrating a list

      Neil Cerutti wrote:
      On 2006-09-01, Tal Einat <tal.no.no.spam @gmail.comwrote :
      Tim Chase wrote:
      I'm not sure if '__iter__' is the right thing to be looking
      for, but it seems to work at least for lists, sets,
      dictionarys (via their keys), etc. I would use it because at
      least then you know you can iterate over it
      AFAIK and as seen throughout posts on c.l.py, the best way to
      check if something is iterable is:

      try:
      iter(obj)
      except TypeError:
      <obj is not iterable>
      else:
      <obj is iterable>
      >
      That confounds me. Of course, I'm coming from a C++, where you
      never want to throw an exception in a common case, hence the name
      'exception'. The Python FAQ does say that raising and catching an
      exception is an expensive operation. I see that type-checking is
      good to avoid, but type-checking must be better than "abusing"
      exceptions in this way. Is the above really a popular idiom?
      >
      If so, I guess I'll get used to it.
      >
      Such use of exceptions is surely common enough in Python to be worth
      getting to know, if only in order to understand others' code.

      If you had wanted to check if an object was callable, which is a more
      basic functionality in Python, you would use Python's built-in function
      callable(). Unfortunately there is no such function as iterable().
      (perhaps there should be? ...)

      Raising an exception is a relatively "expensive" operation, but not so
      much that you would want to avoid it altogether... In most such cases,
      such as checking whether an object is iterable, speed isn't an issue.

      IMO this is far from "abuse". The iter() function's documenation
      explicitly notes "If it does not support either of those protocols,
      TypeError is raised." This can be viewed as one possible output of the
      function, in addition to the possibility of returning an iterator. In
      such a function, raising exceptions instead of returning None or other
      special values (often called "return codes") is much more modular, and
      IMO much more readable.

      - Tal

      Comment

      • Hardcoded Software

        #18
        Re: disgrating a list

        Tal Einat wrote:
        Neil Cerutti wrote:
        On 2006-09-01, Tal Einat <tal.no.no.spam @gmail.comwrote :
        Tim Chase wrote:
        >I'm not sure if '__iter__' is the right thing to be looking
        >for, but it seems to work at least for lists, sets,
        >dictionarys (via their keys), etc. I would use it because at
        >least then you know you can iterate over it
        >
        AFAIK and as seen throughout posts on c.l.py, the best way to
        check if something is iterable is:
        >
        try:
        iter(obj)
        except TypeError:
        <obj is not iterable>
        else:
        <obj is iterable>
        That confounds me. Of course, I'm coming from a C++, where you
        never want to throw an exception in a common case, hence the name
        'exception'. The Python FAQ does say that raising and catching an
        exception is an expensive operation. I see that type-checking is
        good to avoid, but type-checking must be better than "abusing"
        exceptions in this way. Is the above really a popular idiom?

        If so, I guess I'll get used to it.
        Such use of exceptions is surely common enough in Python to be worth
        getting to know, if only in order to understand others' code.
        >
        If you had wanted to check if an object was callable, which is a more
        basic functionality in Python, you would use Python's built-in function
        callable(). Unfortunately there is no such function as iterable().
        (perhaps there should be? ...)
        >
        Raising an exception is a relatively "expensive" operation, but not so
        much that you would want to avoid it altogether... In most such cases,
        such as checking whether an object is iterable, speed isn't an issue.
        >
        IMO this is far from "abuse". The iter() function's documenation
        explicitly notes "If it does not support either of those protocols,
        TypeError is raised." This can be viewed as one possible output of the
        function, in addition to the possibility of returning an iterator. In
        such a function, raising exceptions instead of returning None or other
        special values (often called "return codes") is much more modular, and
        IMO much more readable.
        >
        - Tal
        I agree. Code readability is much more important than code performance
        (Well, in the Python realm.). A Python coder shouldn't care about
        performance until he/she does a profiling and finds out a bottleneck.

        Besides, I like my solution a little better :). When performing the
        extend in the try, the extend will raise TypeError anyway. No need to
        call iter(). It's what my Python in a nutshell book calls "It's easier
        to ask forgiveness than permission" idiom, as opposed to the "Look
        before you leap" idiom.

        Comment

        • Bryan Olson

          #19
          Re: disgrating a list

          Tal Einat wrote:
          Tim Chase wrote:
          >I'm not sure if '__iter__' is the right thing to be looking for,
          >but it seems to work at least for lists, sets, dictionarys (via
          >their keys), etc. I would use it because at least then you know
          >you can iterate over it
          >
          AFAIK and as seen throughout posts on c.l.py, the best way to check if
          something is iterable is:
          >
          try:
          iter(obj)
          except TypeError:
          <obj is not iterable>
          else:
          <obj is iterable>
          It's a trap: there's no good general Pythonic flatten().

          In Tim's version flatten(['hello', [['world']]]) is
          ['hello', 'world']. With the try...except above, it comes
          out ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
          That's not usually what people want.

          It's not just a string problem. Flattening arbitrary
          sequences of Foo-like things assumes that no one
          implements objects that are both Foos and sequences.
          Duck-typing lets you treat lots of types of things
          polymorphically , but it breaks the partitioning by
          kind that flatten() requires.

          Fortunately there's no real need for a general flatten().


          --
          --Bryan

          Comment

          Working...