473,385 Members | 1,593 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

disgrating a list

Hello,

How can I disgrate (probably not a good word for it) a list? For
example:

a = [1,2]
b = 3
c = [a] + [b] # which makes [[1,2],3]

Then how can I change c ([[1,2],3]) into [1,2,3]? I have a simple
function for this:
========================
def flatten(l):
r = []
s = [l]
while len(s) 0:
i = s.pop()
if i.__class__ == list:
for c in i:
s.append(c)
else:
r.append(i)
return r
========================
But this function isn't really doing it in the "python-way". Doesn't
have python an obscure function or buildin to do this?

Greetz,

Noud Aldenhoven

Sep 1 '06 #1
18 1787
jwaixs schrieb:
Hello,

How can I disgrate (probably not a good word for it) a list? For
example:

a = [1,2]
b = 3
c = [a] + [b] # which makes [[1,2],3]
Why do you wrap a in a list? Just

c = a + [b]

will do it.

Diez
Sep 1 '06 #2

Diez B. Roggisch wrote:
Why do you wrap a in a list? Just

c = a + [b]

will do it.
Yes I know, but the problem is I don't know if 'a' is a list or not. I
could make a type check, but I don't want to program in that way.

Noud

Sep 1 '06 #3
jwaixs wrote:
Hello,

How can I disgrate (probably not a good word for it) a list? For
example:

a = [1,2]
b = 3
c = [a] + [b] # which makes [[1,2],3]

Then how can I change c ([[1,2],3]) into [1,2,3]? I have a simple
function for this:
========================
def flatten(l):
r = []
s = [l]
while len(s) 0:
i = s.pop()
if i.__class__ == list:
for c in i:
s.append(c)
else:
r.append(i)
return r
========================
But this function isn't really doing it in the "python-way". Doesn't
have python an obscure function or buildin to do this?
No, it doesn't, but it's easy to roll one on your own, e.g. using a
recursive generator; in fact, if you had searched for "flatten" in the
google group of c.l.py, you'd find this: http://tinyurl.com/ndobk
George

Sep 1 '06 #4
jwaixs wrote:
Hello,

How can I disgrate (probably not a good word for it) a list? For
example:

a = [1,2]
b = 3
c = [a] + [b] # which makes [[1,2],3]

Then how can I change c ([[1,2],3]) into [1,2,3]? I have a simple
function for this:
========================
def flatten(l):
r = []
s = [l]
while len(s) 0:
i = s.pop()
if i.__class__ == list:
for c in i:
s.append(c)
else:
r.append(i)
return r
========================
But this function isn't really doing it in the "python-way". Doesn't
have python an obscure function or buildin to do this?
I'm not sure what makes it against "the python-way"...I would
likely just use a "for" loop structure rather than a while loop.
I would also skip copying the parameter and popping its
elements off. Lastly, I would use a slightly broader test than
asking if the item is a list (to handle sub-classes, sets,
dictionaries, etc):
>>def flatten(x):
.... q = []
.... for v in x:
.... if hasattr(v, '__iter__'):
.... q.extend(flatten(v))
.... else:
.... q.append(v)
.... return q
....
>>flatten([1,2,3])
[1, 2, 3]
>>flatten([1,2,3, [5,6]])
[1, 2, 3, 5, 6]
>>flatten([1,2,3, [5,6, [7,8]]])
[1, 2, 3, 5, 6, 7, 8]
>>flatten([1,2,3, [5, {1:3,5:1},6, set([7,8])]])
[1, 2, 3, 5, 1, 5, 6, 8, 7]

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

I don't know of any builtin that will go to arbitrary depths, and
haven't figured out a clean way to do this with any sort of
list-comprehension, reduce/map call, or anything of the like.
The ability to flatten requires recursing down nested data
structures...recursion is something that list comprehensions,
map()/reduce() commands, etc. aren't so good as (at least as far
as I've learned).

-tkc



Sep 1 '06 #5
jwaixs wrote:
>
Diez B. Roggisch wrote:
>Why do you wrap a in a list? Just

c = a + [b]

will do it.

Yes I know, but the problem is I don't know if 'a' is a list or not. I
could make a type check, but I don't want to program in that way.
Somewhere in the call chain you have made the decision "I want this function
to accept both lists and scalars", but always passing in lists is probably
the better approach. If you want to go with your original idea -- googling
in c.l.py will turn up many more or less optimized variants of flatten()
that basically follow the same approach as yours. There is also
Tkinter._flatten() which you can use though it gives you a tuple, not a
list -- the place at least should meet the "obscurity" criterion :-)

Peter
Sep 1 '06 #6
Tim Chase wrote:
>>def flatten(x):
... q = []
... for v in x:
... if hasattr(v, '__iter__'):
... q.extend(flatten(v))
... else:
... q.append(v)
... return q
...
Let's do some nitpicking on "pythonic" style. A more pythonic way to do
it would be:

try:
q.extend(v)
except TypeError:
q.append(v)

Sep 1 '06 #7

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>

- Tal

Sep 1 '06 #8
On 2006-09-01, jwaixs <jw****@gmail.comwrote:
Hello,

How can I disgrate (probably not a good word for it) a list? For
example:

a = [1,2]
b = 3
c = [a] + [b] # which makes [[1,2],3]

Then how can I change c ([[1,2],3]) into [1,2,3]? I have a
simple function for this:
You might try:

c = a + [b]

instead, to avoid the issue.
But this function isn't really doing it in the "python-way".
Doesn't have python an obscure function or buildin to do this?
I don't know if the following is the Python way, but I think it's
cute:

def flatten(x):
"""Flatten list x, in place."""
i = 0
while i < len(x):
if isinstance(x[i], list):
x[i:i+1] = x[i]
i = i+1

--
Neil Cerutti
In my prime I could have handled Michael Jordan. Of course, he
would be only 12 years old. --Jerry Sloan
Sep 1 '06 #9
On 2006-09-01, Tal Einat <ta************@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.

--
Neil Cerutti
Sep 1 '06 #10
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

Sep 1 '06 #11
jwaixs schrieb:
Diez B. Roggisch wrote:
>Why do you wrap a in a list? Just

c = a + [b]

will do it.

Yes I know, but the problem is I don't know if 'a' is a list or not. I
could make a type check, but I don't want to program in that way.
So you're telling us that

if not isinstance(a, list):
a = [a]
c = a + [b]

is for some reason not desireable, whereas a much more complex (and most
probably utilizing the very same typechecks) flattening is ok for you?

Not a to convincing argument to me.

Diez
Sep 1 '06 #12
def flatten(x):
for i in range(len(x)):
if isinstance(x[i], list):
x[i:i+1] = x[i]
I don't think this does what you want. Try [[[1,2,3]]] as a trivial
example.

A recursive version, that's not as short as yours:

def flatten(x):
"Recursive example to flatten a list"
if isinstance(x,list):
if len(x):
return flatten(x[0]) + flatten(x[1:])
return []
return [x]

Sep 2 '06 #13
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
The recursive generator implementation seems cuter (and I guess more
efficient) to me; YMMV:

def flatten(x):
if not isinstance(x,list):
yield x
else:
for elem in x:
for subelem in flatten(elem):
yield subelem
Or if you want to modify the argument list in place, as in Neil's
solution:

def flatten_in_place(x):
x[:] = flatten(x)
George

Sep 2 '06 #14
Or, (to add needed recursion to your simple loop):

def flatten(x):
"Modified in-place flattening"
for i in range(len(x)):
if isinstance(x[i], list):
x[i:i+1] = flatten(x[i])
return x

This version modifies in-place (as yours does), which may or may not be
what you want, depending on whether or not you need both the flat and
un-flat versions.

Sep 2 '06 #15
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,

Sep 2 '06 #16
Neil Cerutti wrote:
On 2006-09-01, Tal Einat <ta************@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

Sep 2 '06 #17
Tal Einat wrote:
Neil Cerutti wrote:
On 2006-09-01, Tal Einat <ta************@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.

Sep 2 '06 #18
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
Sep 2 '06 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: massimo | last post by:
Hey, I wrote this program which should take the numbers entered and sort them out. It doesnąt matter what order, if decreasing or increasing. I guess I'm confused in the sorting part. Anyone...
10
by: Kent | last post by:
Hi! I want to store data (of enemys in a game) as a linked list, each node will look something like the following: struct node { double x,y; // x and y position coordinates struct enemy...
24
by: Robin Cole | last post by:
I'd like a code review if anyone has the time. The code implements a basic skip list library for generic use. I use the following header for debug macros: /* public.h - Public declarations and...
4
by: JS | last post by:
I have a file called test.c. There I create a pointer to a pcb struct: struct pcb {   void *(*start_routine) (void *);   void *arg;   jmp_buf state;   int    stack; }; ...
3
by: chellappa | last post by:
hi this simple sorting , but it not running...please correect error for sorting using pointer or linked list sorting , i did value sorting in linkedlist please correct error #include<stdio.h>...
0
by: drewy2k12 | last post by:
Heres the story, I have to create a doubly linked list for class, and i have no clue on how to do it, i can barely create a single linked list. It has to have both a head and a tail pointer, and...
10
by: AZRebelCowgirl73 | last post by:
This is what I have so far: My program! import java.util.*; import java.lang.*; import java.io.*; import ch06.lists.*; public class UIandDB {
0
by: Atos | last post by:
SINGLE-LINKED LIST Let's start with the simplest kind of linked list : the single-linked list which only has one link per node. That node except from the data it contains, which might be...
12
by: kalyan | last post by:
Hi, I am using Linux + SysV Shared memory (sorry, but my question is all about offset + pointers and not about linux/IPC) and hence use offset's instead on pointers to store the linked list in...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.