Flatten the Array!

34

9

In this challenge, your task is to create a program which takes in a nested array and returns a single-dimensional flattened array. For Example [10,20,[30,[40]],50] should output [10,20,30,40,50].


Input

The input will be a nested array (eg. [10,20,[[[10]]]]). It will contain only Integers (both negative and positive), Strings and Arrays. You can take the input as function argument, STDIN or whatever suits your language. You can assume that the input array won't have an empty array.


Output

The output will be a flatted single-dimensional array with the same elements of same type as in the nested array and in the SAME order.


Test Cases

[10,20,30] -> [10,20,30]
[[10]] -> [10]
[["Hi"],[[10]]] -> ["Hi",10]
[[[20],["Hi"],"Hi",20]] -> [20,"Hi","Hi",20]
[[["[]"],"[]"]] -> ["[]","[]"]


Feel free to ask for any clarification by using comments. This is , so the shortest code in bytes wins!

Note: If your language contains a built-in for this, then you must NOT use it.


Edit

Please also include a link to a website where your code can be executed.

Arjun

Posted 2016-05-18T04:57:52.677

Reputation: 4 544

7Some languages treat strings as arrays, is [["Hi"],[[10]]] -> ["H","i",10] ok? – Adám – 2016-05-18T05:30:26.580

@NᴮᶻNo, I'm afraid that isn't OK. – Arjun – 2016-05-18T05:37:49.843

1I'm really surprised this isn't a duplicate – Mego – 2016-05-18T06:10:00.297

4@Mego I was surprised too to find out that there was an unflatten question but no flatten question on PPCG. – Arjun – 2016-05-18T06:13:29.240

Is it okay if the output is an array of all strings, but still contain the same values in the same order as the input array? For instance, is it okay if the input [[[20],["Hi"],"Hi",20]] results in the output ['20', "'Hi'", "'Hi'", '20']? – R. Kap – 2016-05-18T09:09:46.177

3What if your language only supports subarrays of the same size? (E.g. Java?) What if the type of each element must be the same? (E.g. Java, C++ etc.?) Also, please add e.g. ["[",[["[",],'[',"['['"]] as a test case. – flawr – 2016-05-18T11:30:54.940

4@flawr That test case only makes sense for languages that support bot ' and " as delimiters. (But I agree that a test case involving [, ], " and \ inside a string would be useful.) – Martin Ender – 2016-05-18T11:40:37.167

4The test cases also exclude languages which do not support these kinds of arrays with multiple types, or with another notation for array literals. – flawr – 2016-05-18T11:42:39.567

@R.Kap Sorry but that's not allowed. I've edited the question also. – Arjun – 2016-05-18T12:00:34.690

3@flawr Of course, but I think we always assume that you just rewrite the test cases with your language's syntax. Making using of something like redundant literal syntax that is only present in some languages seems unnecessarily specific. – Martin Ender – 2016-05-18T12:00:37.823

2@flawr Java can have subarrays of different sizes (but not different types, thus not different 'depths'). – David Conrad – 2016-05-19T06:33:56.590

3@DavidConrad not true - an array is an Object, so an Object[] can contain other arbitrary Object[]. Obviously this isn't typesafe, and any algorithm flattening an Object[] would need to use reflection to work out what's going on. – Boris the Spider – 2016-05-20T07:46:04.400

2In C or asm (where polymorphic data types have to be implemented manually), I'm imagining accepting the multi-dimensional array in serialized form. i.e. treat the problem as a text-processing problem, just removing the internal unquoted [ and ] characters :P – Peter Cordes – 2016-05-22T18:04:54.983

2If your chosen language can't handle nested arrays, why are you worrying about using it for this challenge? It obviously can't do this challenge, which is fine. On a side note, using Object[] in Java and std::any[] in C++17 (or the equivalent boost::any in earlier C++ versions) would work. – Mego – 2016-05-25T05:25:16.370

1What if the language automatically flattens the input? – caird coinheringaahing – 2017-03-23T14:58:57.407

3Requiring support for both numbers and strings just makes this challenge unnecessarily complicated, and deviates from the core task. – Erik the Outgolfer – 2017-11-19T12:57:25.647

A test case like ["1",[2]] would probably be good. – Giuseppe – 2018-03-29T15:09:31.543

Answers

40

K, 3 bytes

,//

This is a fairly common idiom. "Join over converge".

try it here with oK.

How it works:

Join (,) fuses together atoms or lists to produce a list. Over (/) takes a verb (in this case join) and applies it between each element of a list, left to right. Thus, the compound ,/ will flatten all the top level elements of the list. The symbol / actually has different meanings depending on the valence (number of arguments) of the verb with which it is compounded. When we provide ,/ as the verb, the final / acts as "converge"- it repeatedly applies ,/ to the input until it stops changing. Some other languages call a feature like this a "fixed point combinator". By repeatedly fusing bottom level lists, you will eventually arrive at a single flat list, and none of the operations will perturb the order of elements. This seems to solve the problem.

JohnE

Posted 2016-05-18T04:57:52.677

Reputation: 4 632

1All right, thanks for the explanation! Have your well-earned +1. – Value Ink – 2016-05-18T05:52:38.637

a similar solution to a different problem. – JohnE – 2016-05-18T05:53:48.410

1I came up with the same algorithm (but not in this language). +1 for picking the right language to implement it in! – Cyoce – 2016-05-18T05:56:24.543

@Cyoce If your language has equivalents to the three operators used here, it's an extremely natural solution. By all means post your variation. – JohnE – 2016-05-18T05:58:18.810

1@JohnE Long story, I'm deriving a language from algorithms I come up with, so the language isn't finished (and thus implemented) yet. – Cyoce – 2016-05-18T06:02:11.843

gorgeous, marvelous! – Lonely – 2018-01-10T20:46:07.583

38

JavaScript (ES6), 35 bytes

Inspired by @user81655's answer:

f=a=>a.map?[].concat(...a.map(f)):a

Bergi

Posted 2016-05-18T04:57:52.677

Reputation: 967

3Very clever! +1 for [ab]using JS's weird way of handling missing keys! – Cyoce – 2016-05-18T07:03:22.560

I can beat that. – Bald Bantha – 2016-05-19T16:37:22.323

@BaldBantha: We're looking forward for your answer :-) – Bergi – 2016-05-19T16:39:00.057

2Crap NVM My 33 byte solution fails on one of the test cases. NOOOO – Bald Bantha – 2016-05-19T16:39:31.303

@Bergi here it is anyway: i=x=>x.join().split(','); – Bald Bantha – 2016-05-19T16:40:21.463

Nevermind again! your answer does the same thing as mine! brb answering. – Bald Bantha – 2016-05-19T16:43:32.650

2@BaldBantha, join-split will fail on commas inside of strings. – Qwertiy – 2016-05-20T01:18:56.233

19

Mathematica, 16 14 bytes

{##&@@#&//@#}&

An unnamed function which takes and returns a list, e.g.:

{##&@@#&//@#}& @ {{{20}, {"Hi"}, "Hi", 20}}
(* {20, "Hi", "Hi", 20} *)

Explanation

Syntactic sugar party!

To understand how this works, note that every expression in Mathematica is either an atom (e.g. numbers, strings, symbols) or a compound expression of the form f[a, b, c, ...], where f, a, b, c are themselves arbitrary expressions. Here, f is called the head of the expression. Everything else on top of that is just syntactic sugar. E.g. {a, b, c} is just List[a, b, c].

We start with //@ which maps a functions over all levels of a list. For instance:

f //@ {{{20}, {"Hi"}, "Hi", 20}}
(* f[{f[{f[{f[20]}], f[{f["Hi"]}], f["Hi"], f[20]}]}] *)

Note that this maps f over atoms as well as compound expressions. What we're now looking for is a way to get rid of the list heads and keep everything else.

The Apply function is normally used to feed the elements of a list as separate arguments to a function, but its actual definition is more general and simply replaces the head of an expression. E.g. Apply[g, f[a, b]] gives g[a, b].

Now there's a special "head" called Sequence that simply vanishes. E.g. {a, Sequence[b, c], d} just evaluates to {a, b, c, d}. The idea for flattening the list is to replace the heads of all inner lists with Sequence so that they get splatted into their surrounding list. So what we want is to Apply the head Sequence to the lists. Conveniently if we Apply something to an atom, it just leaves the atom unchanged, so we don't have to distinguish between types of expressions at all.

Finally, there's one small issue: f is also applied to the outermost level, so that it also removes the outermost List, which we don't want. The shortest way to counter that is simply to wrap the result in a list again, such that the surrounding Sequence can safely vanish.

Note that there's neither Apply nor Sequence in the code. @@ is an operator form of Apply and ##& is a standard golfing trick to shorten the long built-in name Sequence. So ungolfing everything a bit, we get something like:

flatten[list_] := { MapAll[Apply[Sequence], list] }

For more details on how and why the ##& works, see the section on "Sequences of arguments" in my answer for the Mathematica tips.

Martin Ender

Posted 2016-05-18T04:57:52.677

Reputation: 184 808

First time I've seen //@. Very useful to know about! – DavidC – 2016-05-18T15:03:26.650

//@ captures a neat pattern. Reminds me a bit of some of the recursive combinators in Joy. Do you have a link to a good reference to any related functions in Mathematica? I'm very interested in ways of factoring explicit recursion out of programs. – JohnE – 2016-05-18T16:15:53.303

1

@JohnE Well, here's the docs. You could also look at things like Map, MapAt, Apply, as well as Replace and related functions. In general though there's a lot of function which take an optional levelspec parameter (see my original 16-byte solution), which lets you apply the function at multiple/all levels at once.

– Martin Ender – 2016-05-18T16:25:17.310

12

Python 2, 43 bytes

f=lambda l:[l]*(l*0!=[])or sum(map(f,l),[])

On a list, recurses on the elements and concatenates the results. On a string or number, encases in a singleton list.

Unfortunately, Python 2's ordering for types int < list < string sandwiches list between the others, requiring two inequalities to check. So, instead, l*0 is checked against the empty list [], otherwise giving 0 or "".

xnor

Posted 2016-05-18T04:57:52.677

Reputation: 115 687

10

Ruby, 43 42 34 bytes

Recursive solution. Now with exception handling! (might as well credit @akostadinov for inspiring the change though)

f=->a{a.map(&f).inject:+rescue[a]}

IDEOne link

Value Ink

Posted 2016-05-18T04:57:52.677

Reputation: 10 608

kudos for shortness, awesome – akostadinov – 2016-05-18T21:03:42.750

I didn't know you could use rescue like that – Cyoce – 2016-05-19T01:47:13.850

1@Cyoce I think it's because Ruby technically doesn't have a try block, so you use begin instead to differentiate the parts you want to be catching for and the parts that you don't. So since you're catching for the entire rest of the block before it, you technically don't need it? The rest is just trimmed whitespace, since Ruby interprets the line as ...inject(:+) rescue [a] – Value Ink – 2016-05-19T03:16:44.457

1@KevinLau-notKenny, no, rescue on same line is different, just rescuing that line. e.g. a = raise("haha") rescue 1 would assign 1 to a. It' – akostadinov – 2016-05-19T06:45:14.693

@KevinLau-notKenny There's an inline rescue, like there's an inline if and while. – Fund Monica's Lawsuit – 2016-05-21T16:23:15.513

8

JavaScript (ES6), 41 bytes

f=a=>[].concat(...a.map(v=>v.pop?f(v):v))
<textarea id="input" rows="6" cols="40">[[[20],["Hi"],"Hi",20]]</textarea><br /><button onclick="result.textContent=JSON.stringify(f(eval(input.value)))">Go</button><pre id="result"></pre>

user81655

Posted 2016-05-18T04:57:52.677

Reputation: 10 181

8

Perl 6, 24 bytes

{gather {$_».&{.take}}}

Explanation:

{ # has $_ as an implicit parameter

  gather {

    $_\ # the parameter from the outer block
    »\  # for each single value in the structure
    .&( # call the following block as if it was a method
      { # this block has its own $_ for a parameter
        .take # call the .take method implicitly on $_
      }
    )
  }
}

Test:

#! /usr/bin/env perl6

use v6.c;
use Test;

my &flatten = {gather {$_».&{.take}}}

my @tests = (
  [10,20,30], [10,20,30],
  [[10,],], [10,],
  [["Hi",],[[10,],],], ["Hi",10],
  [[["[]",],"[]"],], ["[]","[]"],
);

plan @tests / 2;

for @tests -> $input, $expected {
  # is-deeply cares about the exact type of its inputs
  # so we have to coerce the Seq into an Array
  is-deeply flatten($input).Array, $expected, $input.perl;
}
1..4
ok 1 - $[10, 20, 30]
ok 2 - $[[10],]
ok 3 - $[["Hi"], [[10],]]
ok 4 - $[[["[]"], "[]"],]

Brad Gilbert b2gills

Posted 2016-05-18T04:57:52.677

Reputation: 12 713

7

Haskell, 43 bytes

data D a=L a|N[D a]
f(L x)=[x]
f(N l)=f=<<l

Haskell has neither nested lists with different depths of the sublists nor mixed types for the list elements. For nesting I define a custom data type D which is either a leaf L that holds some element or a node N which is a list of Ds. For the mixed elements I use the predefined data type Either which combines two types into one, here Either String Integer. The new type D and the flatten function f are fully polymorphic in the type of the leaf elements, so I don't have to take extra care of anything regarding Either.

Usage example: f (N[N[L(Right 20)], N[L(Left "Hi")], L(Left "Hi") , L(Right 20)]) -> [Right 20,Left "Hi",Left "Hi",Right 20].

nimi

Posted 2016-05-18T04:57:52.677

Reputation: 34 639

6

JavaScript (Firefox 30-57), 43 bytes

f=a=>a.map?[for(b of a)for(c of f(b))c]:[a]

Just because I could even avoid using concat.

Neil

Posted 2016-05-18T04:57:52.677

Reputation: 95 035

Isn't it ECMAScript 6 not Firefox 30+? – Solomon Ucko – 2016-05-19T18:49:06.420

1@SolomonUcko No, [for(of)] is only available in Firefox 30+. It was proposed for ES7 but later dropped. – Neil – 2016-05-19T19:29:09.250

1thanks for explaining! Mostly, i just thought it was for(__ in __) – Solomon Ucko – 2016-05-19T21:57:36.777

@SolomonUcko [for(in)] was an alternative experimental syntax which gave you the keys of the object. – Neil – 2016-05-19T23:02:05.817

6

Pyth, 7 6 5 bytes

us+]Y

Try it online: Demonstration or Test Suite

But of course, there is also a build-in function, that handles the task in just 2 bytes: .n (Test Suite)

Jakube

Posted 2016-05-18T04:57:52.677

Reputation: 21 462

Just 3 away from the current winner! +1 – Arjun – 2016-05-18T13:11:25.647

@Sting: Golfed away another byte. Forgot that Pyth append the last character G implicitly, if I don't write it. – Jakube – 2016-05-18T13:25:33.377

Congratulations! – Arjun – 2016-05-18T13:30:47.750

5

Perl, 34 29 bytes

Functions.

If needs to flatten to list like my @a = f(@a), 29 bytes:

sub f{map{ref()?f(@$_):$_}@_}

Test it on Ideone

If needs to flatten to array ref like my $a = f($a), 34 bytes:

sub f{[map{ref()?@{f(@$_)}:$_}@_]}

Test it on Ideone.

Perl 5.22.0+, 27 bytes

Thanks to hobbs.

If needs to flatten to list like my @a = f(@a), 27 bytes:

sub f{map{ref?f(@$_):$_}@_}

Test it on JDoodle

If needs to flatten to array ref like my $a = f($a), 32 bytes:

sub f{[map{ref?@{f(@$_)}:$_}@_]}

Test it on JDoodle.

Denis Ibaev

Posted 2016-05-18T04:57:52.677

Reputation: 876

I haven't tested it, but think ?@{f@$_}: should work instead of ?@{f(@$_)}:, saving two bytes. – msh210 – 2016-05-18T21:29:33.003

1@msh210 No, it’s not working. The compiler doesn’t khow that f is a function because f not yet declared. sub f{}sub f{... f@$_ ...} working. – Denis Ibaev – 2016-05-19T09:52:49.867

>

  • ref doesn't need the parens to work, saving 2 bytes. 2. As far as I can see, sub f{map{ref?f(@$_):$_}@_} is within the rules and saves another 5. f takes an array (nonref) as a list, so it can return the same.
  • < – hobbs – 2016-05-20T00:15:57.177

    @hobbs 1. If no parentheses with ref then the compiler assumes that ? is starting ?PATTERN? operation like ref(?PATTERN?). So the compiler searches second ? and throws error. – Denis Ibaev – 2016-05-20T05:27:44.737

    @DenisIbaev ah. ?PATTERN? was removed in 5.22.0 (m?PATTERN? still works) and I'm testing on a recent version. So you can gain those two bytes by specifying 5.22+. – hobbs – 2016-05-20T05:34:13.440

    @hobbs 2. I thought about it. But I wasn’t sure that it’s within the rules. – Denis Ibaev – 2016-05-20T05:35:35.590

    @hobbs Thanks. I added all versions. – Denis Ibaev – 2016-05-20T06:20:24.727

    4

    Julia, 29 bytes

    f(x,y=vcat(x...))=x==y?x:f(y)
    

    This is recursive splatting into a concatenate function until a reaching a fix point. Example

    julia> f([1,[2,[3,[4,[5,[6]]]]]])
    6-element Array{Int64,1}:
     1
     2
     3
     4
     5
     6
    

    mschauer

    Posted 2016-05-18T04:57:52.677

    Reputation: 1 348

    3

    Retina, 30 bytes

    1>`("(\\.|[^"])+")|[][]
    $1
    $
    ]
    

    Try it online! (The first line is only used to run multiple test cases at once.)

    Retina has no concept of arrays, string literals or numbers, so I decided to go with a "common" input format of [...,...] style arrays and "-delimited strings, where \ can be used inside the strings to escape any character (in particular " and \ itself).

    The program itself simply matches either a full string or a square bracket, and replaces them with $1 which keeps strings and removes square brackets. The limit 1> skips the first match so that we don't remove the leading [. However, this does remove the trailing ], so we add it back in in a separate stage.

    Martin Ender

    Posted 2016-05-18T04:57:52.677

    Reputation: 184 808

    3

    Pyke, 11 bytes

    .F~]+=])K~]
    

    Try it here!

    Explanation:

    .F~]+=])    - Deep for loop
      ~]        -    contents of `]` ([] by default)
        +       -  ^+i
         =]     - `]` = ^
            K~] - Output value
            K   - Remove the output from the for loop
             ~] - Return the contents of `]`
    

    Or 7 bytes after a bugfix

    M?+]K~]
    

    Try it here!

    Explanation:

    M?+]    - Deep map
     ?+]    -  `]` = `]`+i
        K~] - Output value
        K   - Remove the output from the for loop
         ~] - Return the contents of `]`
    

    Or even 2 bytes if printing to stdout is allowed (This might come under built-ins)

    M
    <newline required>
    

    Try it here!

    This deeply applies the print_newline function to every non-sequence item in the input and recurses for sequence items.

    Blue

    Posted 2016-05-18T04:57:52.677

    Reputation: 26 661

    Just 4 away from K! +1 – Arjun – 2016-05-18T13:11:54.837

    3

    Java (v8) 390 276 bytes

    public static Object[] f(final Object[]a) {
        List<Object>r=new ArrayList<>();boolean t=false;int n=0;
        for(final Object p:a)
            if(t=p instanceof Object[]){for(final Object q:(Object[])p) r.add(q);}
            else r.add(p);
        return(t)?f(r.toArray()):r.toArray();
    }  
    

    Just for completeness and all that. :) Can't say Java's code-efficient.

    Jeremy Harton

    Posted 2016-05-18T04:57:52.677

    Reputation: 39

    3Hello, and welcome to PPCG! This question is [tag:code-golf], so please try to minimize your code. Thanks! – NoOneIsHere – 2016-05-18T20:06:02.603

    Do you have any specific suggestions? I have minimized it, Java is just a heavy language. – Jeremy Harton – 2016-05-18T21:30:05.443

    3Remove all the unnecessary spaces, tabs, and newlines. Change oaf to o, and change flatten to f. – NoOneIsHere – 2016-05-18T22:01:16.123

    2You don't need the finals, the whole thing can be a lambda, you don't need public static... – David Conrad – 2016-05-19T06:41:10.087

    1you could save couple characters if you use generics instead object – user902383 – 2016-05-19T09:16:00.577

    1you could also save 2 bytes if you replace false with 1>2, and additional 2 bytes you could get if you declare n but not define (compiler automatically define it as 0) – user902383 – 2016-05-19T09:17:48.473

    @user902383 I don't think you understand generics, but yes in this case I suppose that 'Object' is implied by no specified type. – Jeremy Harton – 2016-05-22T23:23:59.653

    @David Conrad May Lambas are 'eww' in most cases. And yes I could drop the finals and strictly speaking I don't need the keywords. At the end of the day though, there's no point in changes that squeeze out less than maybe 20 bytes because Java isn't (generally speaking) an interpreted language. There's no way it will ever compete with half the languages people chose to use. – Jeremy Harton – 2016-05-22T23:26:00.373

    1It has nothing to do with interpreted languages. This is code golf. And, no, lambdas are not 'eww'. – David Conrad – 2016-05-23T02:04:04.530

    Look, don't play stupid. 'Eww' is a matter of opinion as are many opinions about what is good or bad code and I do in fact have a negative opinion of lambdas/anonymous functions and prefer to avoid using them when I can. – Jeremy Harton – 2016-11-13T21:15:26.777

    2

    ANSI C, 193 bytes

    #define b break;
    #define c case
    #define p putch(_);
    char f;main(_){switch(_){c 1:putch(91);b c 34:f^=1;p b c 91:f&&p b c 93:f&&p b c 10:c 13:putch(93);return;default:p}_=getch();main(_);}
    

    :-/, any suggestions? Btw, I did try to find an online source to compile this but the WL is strict for this code to compile. It will work for VS and gcc otherwise.

    amritanshu

    Posted 2016-05-18T04:57:52.677

    Reputation: 121

    2Welcome to PPCG! – Martin Ender – 2017-05-15T14:35:39.737

    1Welcome to PPCG! Nice first golf. Good luck ahead! – Arjun – 2017-05-15T14:59:41.110

    Thanks! It was an attempt to up my points so that I can get commenting privileges elsewhere. It appears things don't work like that the accounts are for different portals. :D I will see if some nifty features from c++ can be used. – amritanshu – 2017-05-15T15:07:31.480

    2

    JavaScript 20 bytes

    a=>(a+[]).split(',')
    

    The array + array is equal to array.toString

    i--

    Posted 2016-05-18T04:57:52.677

    Reputation: 121

    @WheatWizard thanks for the welcome and I am new to the site. actually a is an argument of the function. I will try to edit out the function now. – i-- – 2017-07-19T15:19:43.710

    I think now it's ok @WheatWizard. Please let me know if there is a problem with this – i-- – 2017-07-19T15:21:31.577

    1Actually looking at the javaScript docs an anonymous function would definitely be shorter, you would only have to add a=> to the beginning of your code. – Post Rock Garf Hunter – 2017-07-19T15:26:06.667

    @WheatWizard I updated with the arrow function as you mentioned. But I have to remove the snippet because arrow function doesn't support direct invoke. It is only for callbacks – i-- – 2017-07-19T15:33:06.960

    Save 2 bytes with split\,`` – Arjun – 2017-07-23T01:11:33.587

    1This doesn't handle strings with commas in them correctly – Jo King – 2019-02-16T10:17:31.937

    2

    C#, 48 bytes

    ()=>{$"[{i.Replace("[","").Replace("]","")}]";};
    

    Thought I'd post it also since nobody has given a C# solution yet. Suggestions welcome!

    PmanAce

    Posted 2016-05-18T04:57:52.677

    Reputation: 131

    Welcome to the site. I haven't programmed in C# in a while but it looks to me that you might have a couple of issues. For one how is i initialized? and are you sure it works on the [["[]"],"[]"] example? – Post Rock Garf Hunter – 2019-02-15T22:58:04.683

    Sorry, i is the input passed in as a string. An empty array would just translate to an empty string. – PmanAce – 2019-02-15T23:07:49.327

    How about the last testcase? Also, I presume you meant to do i=>$"{i.Replace("[","").Replace("]","")}"? – Embodiment of Ignorance – 2019-02-17T00:34:05.770

    Sadly doesn't work in the last case, it will get rid of empty array. :( – PmanAce – 2019-02-17T01:25:20.533

    This answer doesn't pass the final test case. Since it has not been fixed for a few months, I'm voting to delete it. – mbomb007 – 2019-08-05T21:25:29.710

    2

    Python, 57 bytes

    f=lambda a:sum([list==type(x)and f(x)or[x]for x in a],[])
    

    Try it online: Python 2, Python 3

    Thanks to Kevin Lau for the list==type(x) trick.

    Mego

    Posted 2016-05-18T04:57:52.677

    Reputation: 32 998

    2type(x)==list is shorter than isinstance(x,list). – Value Ink – 2016-05-18T05:37:49.640

    1“It will contain only Integers (both negative and positive), Strings and Arrays.” How about [`x`>'['and...? (That works in Python 2 only.) – Lynn – 2016-05-18T11:47:36.030

    2

    Ruby

    there is builtin flatten method.

    You can run here: http://www.tutorialspoint.com/execute_ruby_online.php

    One 43 bytes, but thought to share:

    f=->a{a.inject([]){|r,e|r+(f[e]rescue[e])}}
    

    One 45 bytes that is more efficient than the previous and the other ruby answer:

    f=->a{a.map{|e|Array===e ?f[e]:[e]}.inject:+}
    

    here's benchmark:

    require 'benchmark'
    n=10^9
    arr=[[[20],[[[[[[[[123]]]]]]]],"ads",[[[[[[[4]]]]]]],5,[[[[[[[[[[6]]]]]]]]]],7,8,[[[[[[[[[[9]]]]]]]]]],[[[[[[[[[[0]]]]]]]]]],[[[[[[[[[[[["Hi"]]]]]]]]]]]],[[[[[["Hi"]]]]]],[[[[[20]]]]]]]
    Benchmark.bm do |x|
      x.report { f=->a{a.map(&f).inject:+rescue[a]}; f[arr] }
      x.report { f=->a{a.map{|e|e!=[*e]?[e]:f[e]}.inject:+}; f[arr] }
      x.report { f=->a{a.inject([]){|r,e|r+(f[e]rescue[e])}}; f[arr] }
      x.report { f=->a{a.map{|e|Array===e ?f[e]:[e]}.inject:+}; f[arr] }
    end
    

    result:

           user     system      total        real
       0.010000   0.000000   0.010000 (  0.000432)
       0.000000   0.000000   0.000000 (  0.000303)
       0.000000   0.000000   0.000000 (  0.000486)
       0.000000   0.000000   0.000000 (  0.000228)
    

    akostadinov

    Posted 2016-05-18T04:57:52.677

    Reputation: 211

    1Hello, and welcome to PPCG! Unfortunately, your answer is not valid, because of this rule: Note: If your language contains a built-in for this, then you must NOT use it. – NoOneIsHere – 2016-05-18T20:04:32.033

    @NoOneIsHere, thanks, didn't know that – akostadinov – 2016-05-18T20:22:55.757

    1How does my new update stack against time-wise against yours? Also, just like my new answer, you can remove the spaces around rescue – Value Ink – 2016-05-18T20:59:53.223

    @KevinLau-notKenny updated, thanks! rescue looks to be rather slow btw, like try/catch in java – akostadinov – 2016-05-18T21:08:01.033

    1Update your bytecount, too – Value Ink – 2016-05-18T21:11:46.283

    @KevinLau-notKenny, updated, also altered the faster solution by your example map.reduce and it became shorter and a little faster – akostadinov – 2016-05-18T21:21:35.363

    2

    Perl, 39 34 + 1 (-p flag) 35 bytes

    Oneliner. Inspired by Martin Büttner.

    #!perl -p
    s/("(\\.|[^"])+"|]$|^\[)|[][]/$1/g
    

    Test it on Ideone.

    Denis Ibaev

    Posted 2016-05-18T04:57:52.677

    Reputation: 876

    2

    Clojure, 68 bytes

    (def f #(if(some vector? %)(f(mapcat(fn[z](if(vector? z)z[z]))%))%))
    

    mapcat first applies function to each element and then concats results. So every time it concats one 'nesting level' is lost. Concat does not work on not sequences so elements have to be wrapped into vector if they're not vector.

    You can try it here: http://www.tryclj.com

    (f [[[20],["Hi"],"Hi",20]])
    (f [[["[]"],"[]"]])
    

    cliffroot

    Posted 2016-05-18T04:57:52.677

    Reputation: 1 080

    Nice first code-golf. +1 :) – Arjun – 2016-05-20T11:56:21.830

    1

    PHP, 73 Bytes

    <?array_walk_recursive($_GET,function($i)use(&$r){$r[]=$i;});print_r($r);
    

    Jörg Hülsermann

    Posted 2016-05-18T04:57:52.677

    Reputation: 13 026

    1

    Attache, 14 bytes

    {Reap[Sow@>_]}
    

    Try it online!

    Fortunately, Attache has a "vectorization" operator, which applies a function at the atoms of a list. In this case, all we need to do is to set up a reaper with Reap and Sow all atoms of the input _ with @>. I think it's quite elegant.

    Alternatives

    15 bytes: Fixpoint{`'^^_}

    16 bytes: Fixpoint!&Concat

    17 bytes: {q:=[]q&Push@>_q}

    17 bytes: Fixpoint[&Concat]

    Conor O'Brien

    Posted 2016-05-18T04:57:52.677

    Reputation: 36 228

    1

    Elixir, 74 bytes

    def d(l)do l|>Stream.flat_map(fn x->if is_list(x)do d(x)else[x]end end)end
    

    First Elixir answer, so can probably be golfed a bit.

    Try it online.

    Explanation:

    def d(l)do l|>            # Recursive method taking a list as input:
      Stream.flat_map(fn x->  #  Map over each item `x` of the input-list:
        if is_list(x)do       #   If `x` is a list itself:
          d(x)                #    Do a recursive call with `x`
        else                  #   Else:
          [x]                 #    Simply leave `x` unchanged
        end                   #   End of the if-else statements
      end)                    #  End of the map
    end                       # End of the recursive method
    

    Of course, if builtins were allowed, this could have been 25 bytes instead:

    fn(l)->List.flatten(l)end
    

    Try it online.

    Kevin Cruijssen

    Posted 2016-05-18T04:57:52.677

    Reputation: 67 575

    1

    Jelly, 4 bytes

    ;/ÐL
    

    Try it online!

    Explanation

    ;/   | Reduce by concatenation
      ÐL | Loop until no further changes
    

    Built-in F would be one byte if allowed.

    Nick Kennedy

    Posted 2016-05-18T04:57:52.677

    Reputation: 11 829

    1

    Wolfram Language (Mathematica), 13 bytes

    #~Level~{-1}&
    

    Try it online!

    Un-golfed: F[x_] := Level[x, {-1}]

    picks out the elements of the structure at the last level of its tree form. I'm not sure this counts as "avoiding the builtin" (which would be Flatten).

    Roman

    Posted 2016-05-18T04:57:52.677

    Reputation: 1 190

    1

    Brachylog, 6 bytes

    ċ↰ᵐc|g
    

    Try it online!

    ċ         The input is a list,
        |     and the output is
       c      the concatenation of
     ↰ᵐ       the results of this predicate on the list's elements.
        |     If the input is not a list, then it
         g    wrapped in a list is the output.
    

    Unrelated String

    Posted 2016-05-18T04:57:52.677

    Reputation: 5 300

    1

    Racket, 63 bytes

    (define(f l)(apply append(map(λ(x)(if(list? x)(f x)`(,x)))l)))
    

    Winny

    Posted 2016-05-18T04:57:52.677

    Reputation: 1 120

    1

    JavaScript, 17 Bytes

    a=>eval(`[${a}]`)
    

    Finally, JavaScript's type conversions can be put to some good use! Please note that this will actually output an array, but string conversion (putting it into HTML) causes it to become a comma separated list.

    If comma separated lists are acceptable output, then the following is valid:

    7 Bytes

    a=>""+a
    

    NOTE: Snippet is broken for some reason

    var subject = 
      a=>eval(`[${a}]`)
    <input oninput="try {output.innerHTML = subject(this.value)} catch(e) {output.innerHTML='Invaild Input'}" />
    <div id="output"></div>

    MayorMonty

    Posted 2016-05-18T04:57:52.677

    Reputation: 778

    3This doesn't seem to work when run in the console for input ["["]... I tried running (a=>eval([${a}]))(["["]) and got a SyntaxError – jrich – 2016-05-18T22:35:09.757

    @jrich. You just get this error when you type character by character. If you copy and paste any valid array, it will work as expected. By the way, nice answer SpeedNinja, I would only change oninput event with a button click. – Washington Guedes – 2016-05-24T20:58:37.943

    This doesn't work for strings with commas in them – Jo King – 2019-02-16T10:18:58.870

    1

    Java 8 165 chars

    import java.util.*;<T>T[]f(T[]a){List<T>l=new ArrayList<>();for(T e:a)if(e instanceof Object[])Collections.addAll(l,f((T[])e));else l.add(e);return(T[])l.toArray();}
    

    Ungolfed into a class:

    public class Q80096 {
    
        public static <T> T[] flatten(T[] array) {
            List<T> flattenedList = new ArrayList<>();
            for (T element : array)
                if (element instanceof Object[])
                     Collections.addAll(flattenedList, flatten((T[]) element));
                else
                    flattenedList.add(element);
            return (T[]) flattenedList.toArray();
        }
    }
    

    This answer is based on Jeremy Harton's approach. I used it changed it in some places and created a more golf-like version.

    Frozn

    Posted 2016-05-18T04:57:52.677

    Reputation: 381

    would it be not better when using Arrays.asList() on "array" and then go the foreach with lambda and end this with a Collector? – Serverfrog – 2017-03-23T14:21:22.063

    0

    Lua, 123 bytes

    function f(a)o,t={},function(s)for _,v in next,s do if type(v)=="table"then t(v)else o[#o+1]=v end end end t(a)return o end
    

    I'm sure this is not the best answer, but I thought I'd post it since nobody has given a Lua solution yet. Suggestions welcome!

    Try it online!

    MCAdventure10

    Posted 2016-05-18T04:57:52.677

    Reputation: 103

    0

    PowerShell, 35 bytes

    filter f{if($_.Rank){$_|f}else{$_}}
    

    Try it online!

    Rank - Returns the number of dimensions in the array. Rank = 0 if an object is not array.

    mazzy

    Posted 2016-05-18T04:57:52.677

    Reputation: 4 832

    0

    C# (Visual C# Interactive Compiler), 72 bytes

    T[]f<T>(T[]a)=>a.SelectMany(x=>x is T[]?f(x as T[]):new[]{x}).ToArray();
    

    Try it online!

    Recursive function that takes an object[] as input. Yes, there is a type parameter, so you could pass an array of any type... But it only works correctly if all nested arrays are of the same type. That is a requirement that I have added :)

    It would be more flexible to get this to work with an input of type IList or Array.

    dana

    Posted 2016-05-18T04:57:52.677

    Reputation: 2 541