Filtering deeply nested elements in TypeScript/JavaScript using advanced techniques

Given the provided structure and data:

interface GrandChild {
    id: number,
    values: Array<string>,
}

interface Child {
    id: number,
    subItems: Array<GrandChild>
}

interface Foo {
    items: Array<Child>
}

const data: Foo = {
    items: [
        { id: 1, subItems: [ { id: 10, values: ['10', '100'] }, { id: 11, values: ['11', '110', '1100'] } ] },
        { id: 2, subItems: [ { id: 20, values: ['REMOVE', 'REMOVE'] }, { id: 21, values: ['REMOVE'] } ] },
        { id: 3, subItems: [ { id: 30, values: ['REMOVE'] }, { id: 31, values: ['REMOVE'] }, { id: 32, values: ['REMOVE', '32'] } ] },
    ]
};

How can I utilize Array methods (filter, map, some, etc.) to achieve the desired outcome?

const expected: Foo = {
    items: [
        { id: 1, subItems: [ { id: 10, values: ['10', '100'] }, { id: 11, values: ['11', '110', '1100'] } ] },
        { id: 3, subItems: [ { id: 32, values: ['32'] } ] },
    ]
}

Initially, I implemented a filter to eliminate unwanted elements from the resulting data:

const filteredData: Foo = {
    ...data,
    items: data.items.map(item => ({
        ...item,
        subItems: item.subItems.map(subItem => ({
            ...subItem,
            values: subItem.values.filter(value => value !== 'REMOVE')
        }))
    }))
}

Resulting in:

{
    items: [
        { id: 1, subItems: [ { id: 10, values: ['10', '100'] }, { id: 11, values: ['11', '110', '1100'] } ] },
        { id: 2, subItems: [ { id: 20, values: [] }, { id: 21, values: [] } ] },
        { id: 3, subItems: [ { id: 30, values: [] }, { id: 31, values: [] }, { id: 32, values: ['32'] } ] },
    ]
};

However, I'm currently struggling to remove empty subItems elements without additional looping through the result.

You can explore the code above online here.

Answer №1

If your goal is to use solely filter and map, you can add a filter after each map to eliminate subItems with empty values arrays and remove items with empty subItems arrays:

const filteredData = {
    ...data,
    items: data.items
        .map((item) => ({
            ...item,
            subItems: item.subItems
                .map((subItem) => ({
                    ...subItem,
                    values: subItem.values.filter((value) => value !== "REMOVE"),
                }))
                .filter(({ values }) => values.length > 0), // ***
        }))
        .filter(({subItems}) => subItems.length > 0),       // ***
};

However:

  • For cases where there's a map followed by filter, consider the performance impact based on the size of the data.
  • When dealing with many nested map calls, think about readability and if using simpler loops would be clearer in the long run.

If you decide that simplifying is the way to go, you could do something like this:

const filteredData: Foo = {
    ...data,
    items: [],
};
for (const item of data.items) {
    const subItems: Array<GrandChild> = [];
    for (const subItem of item.subItems) {
        const values = subItem.values.filter((value) => value !== "REMOVE");
        if (values.length) {
            subItems.push({
                ...subItem,
                values,
            });
        }
    }
    if (subItems.length > 0) {
        filteredData.items.push({
            ...item,
            subItems,
        });
    }
}

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

Manipulating JSONArrays in JAVA by adding a new element to a JSONObject

What is the best way to add an element into a JSONArray without creating multiple arrays using the "append" method? Below is a sample code example with JUnit that demonstrates the issue: import org.codehaus.jettison.json.JSONArray; import org.codehaus.je ...

Steps to programmatically update Node modules:

I am looking to incorporate the use of npm update within a script. Take a look at my code snippet below: var npm = require('npm'); npm.load(function () { npm.commands.outdated({json: true}, function (err, data) { //console.log(data); npm ...

Can the execution of setTimeout() impact the overall performance?

Is it possible that this code will cause the client to slow down due to the extended timeout? //and let's revisit this after some time setTimeout(function() { updateWeather(lat,lng); }, 60000); ...

Angular directive used to create a nested tree list

Currently struggling with a nested list Directive in Angular. Whenever I attempt to run the code, the browser crashes due to the recursive call of the directive. My goal is to display a new list item if the data's children property contains items. H ...

Is tsconfig.json Utilized by Gatsby When Using Typescript?

Many blog posts and the example on Gatsby JS's website demonstrate the use of a tsconfig.json file alongside the gatsby-plugin-typescript for TypeScript support in Gatsby. However, it seems like the tsconfig.json file is not actually utilized for conf ...

What is the best method to fetch a specific post from supabase for showcasing in a dynamic Route with Nextjs14?

I'm currently working on a Next.js application where I am fetching posts from a Supabase database. Everything works fine when retrieving all posts, but when trying to retrieve a single post dynamically using the ID, the screen displays null. Here&apos ...

angular table cell with a show more/less button

I'm trying to create a button that can hide/unhide text in a table cell if the length is greater than a certain number. However, the current implementation is not working as expected. The button ends up opening all texts in every cell, and it only wor ...

Failed to establish Modbus TCP connection

Currently, I am utilizing the "Panasonic FP7" master PLC along with their official software "FPWIN GR7" to monitor data flow on my PC. However, since the software lacks certain functions, I have decided to develop a solution using nodeJS. Below is the code ...

Alter a prototype method belonging to another module

If I wanted to create a custom plugin or module that alters the behavior of an object exported in another module, how can I go about modifying one of its methods? The code below illustrates my attempt at achieving this, but it seems like there may be a cru ...

jQuery's callback handling often reverses the statement I just made

My current project involves using AJAX with jQuery to send a get request. Once the request is successful, I insert the response into a specific div: $.get("content.php", function(result) { $('#content').html(result); The content I'm fetc ...

tallying the amount of negative values within an array

Searching for the negative numbers count in a 2D array (square matrix) is the task at hand. In the matrix, numbers increase as you move from top to bottom and left to right. The logic here involves starting from the last column and moving to the left. If a ...

Can you please explain the significance of file.max and file.FBX within the context of a model in three.js

I am currently working on developing a video game using three.js. Recently, I downloaded a model from the internet and upon checking the directory, I found the following files: city.obj city.mtl city.max city.FBX After some research, I learned that cit ...

What is preventing me from extracting the callback function from the app.get method in Node.js and Express?

In my server.js file, I'm attempting to do the following: // This code is not functioning as expected, and I am unsure why. var findBooks = function (err, books) { if (!err) { return response.send(books); } else { console.log( ...

Phonegap app developer encounters issue with sending ajax requests

Recently, I encountered an issue with Ajax in my Phonegap development. Previously, it worked perfectly but now when I call the Ajax function, nothing happens. Here are the steps I have taken to troubleshoot: 1) I edited the config.xml file and added the f ...

Making the most of Java's array expansion

When working in C/C++, the realloc function efficiently allocates additional space for an existing collection. I have seen discussions indicating that its complexity may be sub-linear or even constant. I am curious if there is a similar way to achieve thi ...

Getting Json data in Android: a guide to fetching data by id and displaying it in a textview

Is there a way to extract specific data from a JSON object using an ID and display it in a TextView without utilizing a ListView? I have successfully retrieved the data in a ListView, but I need to do so in a basic TextView for each individual ID. I am in ...

Get the HTML file converted to a DOCX format that is compatible with Mac Pages

I am currently working on a Next.js application using TypeScript, and I want to give users the ability to download a page as a DOCX file. Initially, I was excited to discover that this could be easily accomplished by following this method. However, after ...

Transform a string containing spaces into a uint16 data type

Hi, I'm seeking assistance with converting a string into an array of uint16. Here is an example of how my string appears: Dim test as String = "4 7 9 10 11 12 14 15 16 17 19 23 24 25 26 27 28 29 30 32 33 37 40 42 48 58 64 65 66 67 68 69 70 71 72 73 ...

PHP Warning when using $_POST as argument in array_key_exists()

Currently, I am implementing the following code style: if(array_key_exists('some_value', $_POST)){echo 'hi';} When using this code in PHP 5.2.17, I encountered a warning. The warning message is as follows: WARNING: argument 2 for array ...

Problem encountered with @HostListener

In an Angular component, I have the following code snippet that is functioning as intended: @HostListener('document:click', ['$event']) onClick(event) { if(!this.eRef.nativeElement.contains(event.target)) { console.log("clicked out ...