News for hackers. Stuff that matters.
Re:Why it’s hard for programmers to write a program to flatt... by contravariant on Friday February 24, 2017 @10:31AM (#13724510)
Couldn't you just do something like:

    def flatten(x):
        if isIterable(x):
            for y in x:
                yield from flatten(y)
        else:
            yield x
Well, technically this is a generator, but it's easy enough to put its result in a list.
Re:Why it’s hard for programmers to write a program to flatt... by Latty on Friday February 24, 2017 @11:57AM (#13725369)
The definition of isIterable here is a bit fun. In most real world cases, you end up needing to specify it down a bit:

   isinstance(el, collections.Iterable) and not isinstance(el, str)
Is the most common one. The first clause to check if it's an iterable (as per the collections.Iterable abstract base class - for those unfamiliar, basically a check for the `__iter__()` method), the second to check it's not a string, which is also iterable, but generally you don't want to split into individual letters - and if you do, you'll need to add more checks as strings split to other 1-length strings that are still iterable, making an infinite loop.

Of course, the original problem did state "lists" explicitly, so I guess you could just type check for lists, but that's really unpythonic and not useful in the real world.

Re:Why it’s hard for programmers to write a program to flatt... by andr3w321 on Friday February 24, 2017 @04:18PM (#13727985)
Some python 2

    def flatten(x):
        def flatten_generator(x):
            if type(x) == list:
                for y in x:
                    for z in flatten(y):
                        yield z
            else:
                yield x
        return list(flatten_generator(x))

    assert(flatten([1, [2,3]]) == [1,2,3])

    ary = [1, [2,3], [4, [5,6]]]
    print flatten(ary)
Re:Why it’s hard for programmers to write a program to flatt... by falcolas on Saturday February 25, 2017 @10:26AM (#13731926)
I'd personally change `if type(x) == list` to `if isinstance(x, (list, tuple, set))` to catch all common iterables and their subclasses.
Re:Why it’s hard for programmers to write a program to flatt... by fiedzia on Friday February 24, 2017 @11:04AM (#13724829)
Sure, the point is that writing this requires knowing more than most candidates do.
Re:Why it’s hard for programmers to write a program to flatt... by amyjess on Friday February 24, 2017 @10:45AM (#13724644)
I found this on Stack Overflow a while back, and I've been using it in my Python code since then:

    [item for sublist in l for item in sublist]
Re:Why it’s hard for programmers to write a program to flatt... by Latty on Friday February 24, 2017 @11:46AM (#13725255)
As others have pointed out, that only flattens one level (which, admittedly, is a much more useful thing most of the time - arbitrarily deeply nested structures are relatively rare).

If you do want to do this, the better method is:

  itertools.chain.from_iterable()
That has the advantage of being lazy, as opposed to a list comprehension, and has the potential to be more optimised. It also doesn't rely on the somewhat obscure and relatively hard to read nested list comprehension syntax.

Docs: https://docs.python.org/3.6/library/itertools.html#itertools...

Re:Why it’s hard for programmers to write a program to flatt... by klibertp on Friday February 24, 2017 @11:32AM (#13725095)
That wouldn't work in this case: it only works with lists where every element is also a list and it only flattens one level deep.

With these constraints, there are quite a few interesting techniques, for example in Scheme you can apply append:

    (apply append list-of-lists)
or in Python you can use reduce with add operator:

    reduce(op.add, list_of_lists) # op == operator module
And anyway, even if it's not the constrained version, the solution is indeed trivial, for example in Erlang:

    flatten(L) -> flatten(L, []).

    flatten([], Acc)            -> Acc; 
    flatten([[] | T], Acc)      -> flatten(T, Acc); 
    flatten([[_|_]=H | T], Acc) -> flatten(T, Acc ++ H);
    flatten([X | T], Acc)       -> flatten(T, Acc ++ [X]).
(please don't mind the inefficient use of ++, it's a toy example...)

It can get a bit more complex in a statically typed language, especially if you want to have static guarantees (no down-casting from Object), but it's still doable in a couple of minutes...

...is what this post - and discussion - is not about.

It's trivial once you get it, of course. But it's also true that it's almost impossible to figure it out on your own during a stressful interview if you didn't get it beforehand. It's so easy to forget that. We all once struggled with some concepts, and we all went through many discoveries of facts, techniques, and skills we didn't know existed, much less that we needed them.

What I want to say is that the beginners who fail to answer this question are not bad, they are just beginners. It's ok to reject them right now, but it's not ok to post an article suggesting that "programmers find it hard to solve trivial problems even with my help". It's not programmers, but beginner programmers; it's not trivial problem, just relatively widely known one; and it may well be the help was insufficient.

Re:Why it’s hard for programmers to write a program to flatt... by amyjess on Friday February 24, 2017 @05:21PM (#13728482)
Thank you for the correction!
Re:Why it’s hard for programmers to write a program to flatt... by contravariant on Friday February 24, 2017 @01:27PM (#13726220)
Like others have pointed out you should have used recursion. Although, if you really wanted to you can make one similar to yours that doesn't (explicitely) use recursion. That results in the following:

    flatten = (lambda f: lambda *args: 
     (lambda x: lambda *args2: f(x(x))(*args2))
     (lambda x: lambda *args2: f(x(x))(*args2))(*args))(
        lambda f: lambda l: [item for sublist in l for item in f(sublist)] if isIterable(l) else [l]
    )
Re:Why it’s hard for programmers to write a program to flatt... by fiedzia on Friday February 24, 2017 @11:05AM (#13724846)
That's not generic and would not qualify as valid answer for this question.
Re:Why it’s hard for programmers to write a program to flatt... by NicoJuicy on Friday February 24, 2017 @12:27PM (#13725629)
That's almost the exact same code as I thought, but it's an extension on c# and uses 'is Enumerable'. Which language is this?
Re:Why it’s hard for programmers to write a program to flatt... by contravariant on Friday February 24, 2017 @12:46PM (#13725811)
It should work in python 3.3+, provided you make a method isIterable to detect whether something is an iterator or not. For lower versions of python you can't use the phrase 'yield from', so you need to iterate over flatten(y) manually and yield each element.