TechnoKnight
TechnoKnight

Reputation: 961

.flat() is not a function, what's wrong?

The following code

function steamrollArray(arr) {
  // I'm a steamroller, baby
  return arr.flat();
}

steamrollArray([1, [2], [3, [[4]]]]);

returns

arr.flat is not a function

I tried it in Firefox and Chrome v67 and the same result has happened.

What's wrong?

Upvotes: 80

Views: 89643

Answers (11)

user21087629
user21087629

Reputation:

You can set your full array to a string then split it. .toString().split(',')

Updated due to community bot. So basically if you want to flatten out an array that does contain any objects but strictly strings or numbers, by using .toString() it converts each element of the array to a string (if it isn't already), and then joins all of the elements together using a comma as a separator.

Once we have our string all separated by a comma we can use .split() to create an array.

NOTE*** The reason this wont work with objects is that .toString() will return [object object] as it is the default string representation of an object in JavaScript.

If your array consists solely of numbers than you would need to map through your array and convert each string number value to a number.

const array1 = [
  ['one', 'oneTwo'],
  'two',
  'three',
  'four',
]
console.log('a1', array1.toString().split(','))

const numberArray = [1, 2, [3, 4, [5, 6]], [[7, [8,9]]], 10]; 
console.log(numberArray.toString().split(',').map(num => Number(num)));

Upvotes: 0

kelvin nyadzayo
kelvin nyadzayo

Reputation: 93

you could simply use this [].concat(...objArrs) that would work the same as the flat() method and allow more compatibility in browsers

Upvotes: 0

AntiRakPro
AntiRakPro

Reputation: 31

var arr=[[1,2],[3,4],[5,6]];
var result=[].concat(...arr);
console.log(result);    //output: [ 1, 2, 3, 4, 5, 6 ]

Upvotes: 1

NITRINO
NITRINO

Reputation: 1

const array = [
  [
    [6, 6],
    [3, 3],
  ],
  [[7, 7, [9]]],
]

function simplifyArray(array) {
  const result = []

  function recursivePushElem(arr) {
    arr.forEach(i => {
      if (Array.isArray(i)) recursivePushElem(i)
      else result.push(i)
    })
  }
  recursivePushElem(array)

  console.log(result)
  return result
}

simplifyArray(array)

Upvotes: 0

Mo.
Mo.

Reputation: 27445

Another simple solution is _.flattenDeep() on lodash

https://lodash.com/docs/4.17.15#flattenDepth

const flatArrays = _.flattenDeep([1, [2], [3, [[4]]]]);

console.log(flatArrays);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

Upvotes: 0

irina
irina

Reputation: 1341

Similar issue, solved by using ES6 .reduce() method:

const flatArr = result.reduce((acc, curr) => acc.concat(curr),[]);

Upvotes: 5

resu
resu

Reputation: 1144

Array.flat is not supported by your browser. Below are two ways to implement it.

As a function, the depth variable specifies how deep the input array structure should be flattened (defaults to 1; use Infinity to go as deep as it gets) while the stack is the flattened array, passed by reference on recursive calls and eventually returned.

function flat(input, depth = 1, stack = [])
{
    for (let item of input)
    {
        if (item instanceof Array && depth > 0)
        {
            flat(item, depth - 1, stack);
        }
        else {
            stack.push(item);
        }
    }
    
    return stack;
}

As a Polyfill, extending Array.prototype if you prefer the arr.flat() syntax:

if (!Array.prototype.flat)
{
    Object.defineProperty(Array.prototype, 'flat',
    {
        value: function(depth = 1, stack = [])
        {
            for (let item of this)
            {
                if (item instanceof Array && depth > 0)
                {
                    item.flat(depth - 1, stack);
                }
                else {
                    stack.push(item);
                }
            }
            
            return stack;
        }
    });
}

Upvotes: 16

dubucha
dubucha

Reputation: 1057

This can also work.

let arr = [ [1,2,3], [2,3,4] ];
console.log([].concat(...arr))

Or for older browsers,

[].concat.apply([], arr);

Upvotes: 36

Bash Lord
Bash Lord

Reputation: 123

use _.flatten from lodash package ;)

Upvotes: 2

giannis christofakis
giannis christofakis

Reputation: 8321

Not sure if it is a valid answer however in my attemp to flat an array I employed the destructuring_assignment introduced in ES6.

// typeScriptArray:Array<Object> = new Array<Object>();
let concatArray = [];

let firstArray = [1,2,3];
let secondArray = [2,3,4];

concatArray.push(...firstArray);
concatArray.push(...secondArray);

console.log(concatArray);

It works like a charm even though I'm not sure if any broswer compatibily issues may arise.

Upvotes: -3

Ivan
Ivan

Reputation: 40618

The flat method is not yet implemented in common browsers (only Chrome v69, Firefox Nightly and Opera 56). It’s an experimental feature. Therefore you cannot use it yet.

You may want to have your own flat function instead:

Object.defineProperty(Array.prototype, 'flat', {
    value: function(depth = 1) {
      return this.reduce(function (flat, toFlatten) {
        return flat.concat((Array.isArray(toFlatten) && (depth>1)) ? toFlatten.flat(depth-1) : toFlatten);
      }, []);
    }
});

console.log(
  [1, [2], [3, [[4]]]].flat(2)
);

The code was taken from here by Noah Freitas originally implemented to flatten the array with no depth specified.

Upvotes: 79

Related Questions