Is employing flat map in this manner considered appropriate?

When I was responding to a question on Stack Overflow about flattening nested arrays, I provided a solution using recursive flattening.

var exampleArray = [ [1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]] ];

function findArrayLengths(input) {
  return input.reduce((op,cur)=>{
    return Array.isArray(cur) ? op.concat(findArrayLengths(cur)) : op.concat(cur)
  },[])
}

let op = exampleArray.map(e=>{
  return findArrayLengths(e).length
})

console.log(op);

However, I noticed that another code snippet also works well for deep flattening (flat with infinite depth). I looked into Array.prototype.Flat

var arr = [ [1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]], [[1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]]] ];

let op = arr.map(e=> e.flat(Infinity).length);

console.log(op);

So the question is: Is it a proper way to do deep flattening with flat like this, or are there any consequences? ?

You can find more information and the original question here.

Answer №1

One way to approach this problem in ES6 is by utilizing the .reduce method instead of forEach.

const exampleArray = [ [1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]] ];

const flatten = (items) => {
  const flat = [];
  items.forEach(item => {
    if (Array.isArray(item)) {
      flat.push(...flatten(item));
    } else {
      flat.push(item);
    }
  });
  return flat;
}

const do_flat = (arr) =>  arr.map( (curr) => flatten(curr).length);

const output = do_flat(exampleArray);

console.log({output});

Answer №2

Is it acceptable to use Array#flat(Infinity) for deep flattening, or are there any drawbacks?

There are no consequences; Array#flat(Infinity) works fine. The only issue is with browser/backwards compatibility.

I wasn't sure if the specification specifies how to handle the passed depth, so using Infinity should be safe across all browsers; in short, it is clearly defined and safe to use.


However, I do have a concern about your fallback code. The way you're using Array#concat() creates unnecessary intermediate Arrays.

A better approach would be:

var exampleArray = [
  [1, 2, 3, 4],
  [1, 2, [1, 2, 3]],
  [1, 2, 3, 4, 5, [1, 2, 3, 4, [1, 2, 3, 4]]]
];

function _flatten(acc, value) {
  if (Array.isArray(value)) {
    return value.reduce(_flatten, acc);
  }

  acc.push(value);
  return acc;
}

function flatten(array) {
  return array.reduce(_flatten, []); 
}

console.log(exampleArray.map(e => flatten(e).length));


//or since you already named your function `findArrayLength`
function _findArrayLength(count, value) {
  return Array.isArray(value) ? value.reduce(_findArrayLength, count) : count + 1;
}

function findArrayLength(array) {
  return array.reduce(_findArrayLength, 0);
}

console.log(exampleArray.map(findArrayLength));
.as-console-wrapper{top:0;max-height:100%!important}

Alternatively, a more generic implementation can be used:

var exampleArray = [
  [1, 2, 3, 4],
  [1, 2, [1, 2, 3]],
  [1, 2, 3, 4, 5, [1, 2, 3, 4, [1, 2, 3, 4]]]
];

function reduceRecursive(fn, init) {
  function _(acc, value, index, array) {
    return Array.isArray(value) ? value.reduce(_, acc) : fn(acc, value, index, array);
  }
  return function(array){
    return array.reduce(_, typeof init === "function" ? init() : init);
  }
}

var flatten = reduceRecursive(function(result, value) {
  result.push(value);
  return result;
}, Array);

console.log(exampleArray.map(e => flatten(e).length));

var findArrayLength = reduceRecursive(function(count) {
  return count + 1;
}, 0);

console.log(exampleArray.map(findArrayLength));
.as-console-wrapper{top:0;max-height:100%!important}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for switching directories and renaming a file when uploading in nodeJs?

I am currently using multer and fs to handle the upload of an image file. How can I modify the directory where uploaded files are stored? Currently, all files are saved in my "routes" folder instead of the "uploads" folder created by multer. Additionally, ...

Using Handlebars: Send the position of every item to a nested statement

Is it possible to pass each index or key to the nested expression in handlebars? //Not working {{#each thumbs}} <img src="{{src}} data-large="{{../<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cfa6a2aea8aabce18 ...

The function passport.authenticate does not exist / User.findone is not a valid function

**I'm really struggling to figure out what I'm doing wrong. I'm new to passport and JavaScript in general, so any help would be appreciated! Every time I try to run it, I get an error saying 'authenticate is not a function'. Then, ...

Dealing with code issues in Subscription forms using AJAX and JQuery

Currently, I am independently studying jQuery and grappling with the Mailchimp Opt-In form code. Despite various existing queries on this topic, I am curious about why my own implementation, as a beginner in jQuery, is not functioning correctly. My intenti ...

What is the best way to add a separator in a b-dropdown menu once the options have been loaded using Vue?

Here is the code snippet for my dropdown element: <b-dropdown id="SchemaDropdown" name="SchemaDropdown" variant="form-control" class="" style="width: 100%" ...

Mastering the art of manipulating arrays with jquery

Trying to implement a dynamic search bar feature using jQuery. Here is the code snippet: Fiddle : https://jsfiddle.net/fpLf1to4/ var inputSearch = $('.searchInput').hide(); var searchArray = ['s','e','a',& ...

Switch up Three.js texture in externally imported Collada model

Currently, I am using the three.js collada loader to bring in an .dae file that includes a texture (.png) image. The challenge I am facing involves replacing this original .png file with a new texture generated from a canvas element and saved in .png forma ...

leveraging hooks in NextJS app router for static page generation

How can I make an action take effect on page-load for the app router equivalent of statically generated pages from static paths in NextJS? Everything is working fine with my page generation: // app/layout.js import Providers from '@/app/Providers&apo ...

Dealing with large integers in JSON when inserting them into a MongoDB database can be a complex task

Challenge : I am dealing with a highly intricate json file that contains integer values exceeding 8 Bytes (c_time, p_time), along with some smaller ones like id in the example below. Sample structure: { "c_time": 18446744062065078000 ...

What is the best way to recreate the functionality of nth-child in JavaScript?

In my current project, I'm attempting to replicate the functionality of CSS using JavaScript. Specifically, I am working with an index of items in a mapped array and assigning each item a unique index number. computed: { parsedItems() { ...

Angular: The dilemma of choosing between updating individual properties or reassigning objects

I am currently working with an object structure that looks like this: steps:any = [ { id: 1, name: "A", next: [{ id: 2, name: "B" }, { id: 3, name: "C" }] }, { id: 2, name: "B", next: [{ id: 1, name: "B" }] }, { ...

The Function(JS) is specifically designed to only function within the topmost div or quote

Currently, I am facing an issue with a function I have implemented. This function adds a blur effect to words in a Blockquote when the page is loaded. However, I need this function to work for all Blockquotes and different divs on the page, not just the to ...

Can you explain the purpose of CLOUDINARY_DEFAULT_URL and CLOUDINARY_DEFAULT_PUBLICID to me?

Need help with my user sign up page Here is my .env file This is my signup controller code: const User = require('../model/User'); const bcrypt = require('bcrypt'); const { uploadToCloudinary } = require('../utils/cloudinary&apos ...

Should arrays of objects be kept in databases or JavaScript files?

Here is a small excerpt from an array of objects utilized on my website. It's just a snippet and not the full JS file. I have several JS files like this, some reaching up to 500 lines of code. Currently delving into databases ...

Limiting character elements in an array in PostgreSQL

In PostgreSQL version 10.1, I have created the following table: CREATE TABLE nationality_cumulative_criteria ( id smallint NOT NULL, country_set character varying(2)[] NOT NULL, number smallint NOT NULL ); I am looking ...

callback triggering state change

This particular member function is responsible for populating a folder_structure object with fabricated data asynchronously: fake(folders_: number, progress_callback_: (progress_: number) => void = (progress_: number) => null): Promise<boolean ...

What is the best way to retrieve the items stored within the array generated by a JavaScript function?

This particular function is responsible for calling a PHP script that outputs JSON data. It then iterates through the JSON object, creates a new object, and adds this new object to an array which is ultimately returned by the function. function getTestQues ...

The property of Three.js Quaternion is immutable and cannot be reassigned

I'm attempting to develop a class (using three.js) that utilizes an array containing vector names to compare with an array containing a set of 3D vectors in order to generate a mesh of a flat face. However, I am encountering an error. Uncaught TypeEr ...

How can Request.UrlReferrer be configured using client-side JavaScript? If it can be done, what is the process?

In my application, I heavily rely on Request.UrlReferrer to handle link clicks and maintain a page history for users. Due to new requirements, I now need to navigate to a specific location using <input type="button" /> instead of <a href="mypage. ...

Javascript redirection not functioning correctly

Currently, I am working with PHP Codeigniter. The current URL of my page is => http://localhost.hbs.com/hbs/merchant/login I want to redirect my page to => http://localhost.hbs.com/hbs/category when a specific event occurs. I have attempted to achie ...