最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to update value of nested array of objects - Stack Overflow

programmeradmin3浏览0评论

This is my actual array :

let mainArray= [
    {
        value: '/AG_TURF-123',
        label: 'Ag & Turf',
        checked: false,
        id:123,
        children: [
            {
                value: '/AG_TURF-123/TRACTOR-456',
                label: 'Tractors',
                checked: false,
                id:456,
                children: [
                    {
                        value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series',
                        label: 'Large (7, 8, 9) Series',
                        checked: false,
                        id:789,
                        children: [{
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor',
                            label: '7 Family Tractor',
                            checked: false,
                            id:101112
                        },{
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor',
                            label: '8 Family Tractor',
                            checked: false,
                            id:131415
                        },{
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor',
                            label: '9 Family Tractor',
                            checked: false,
                            id:161718
                        }],
                    },
                    {
                        value: '/app/Http/routes.js',
                        label: 'routes.js',
                        checked: false,
                        id:181920
                    },
                ],
            },
            {
                value: '/app/Providers',
                label: 'Providers',
                checked: false,
                id:212223,
                children: [{
                    value: '/app/Http/Providers/EventServiceProvider.js',
                    label: 'EventServiceProvider.js',
                    checked: false,
                    id:242526
                }],
            },
        ],
    },
    {
        value: '/config',
        label: 'config',
        checked: false,
        id:272829,
        children: [
            {
                value: '/config/app.js',
                label: 'app.js',
                checked: false,
                id:303132
            },
            {
                value: '/config/database.js',
                label: 'database.js',
                checked: false,
                id:333435
            },
        ],
    },
    {
        value: '/public',
        label: 'public',
        checked: false,
        id:353637,
        children: [
            {
                value: '/public/assets/',
                label: 'assets',
                checked: false,
                id:383940,
                children: [{
                    value: '/public/assets/style.css',
                    label: 'style.css',checked: false,
                    id:404142
                }],
            },
            {
                value: '/public/index.html',
                label: 'index.html',
                checked: false,
                id: 434445
            },
        ],
    },
    {
        value: '/.env',
        label: '.env',
        checked: false,
        id: 464748
    },
    {
        value: '/.gitignore',
        label: '.gitignore',
        checked: false,
        id: 495051
    },
    {
        value: '/README.md',
        label: 'README.md',
        checked: false,
        id: 525354
    },
];

This is my list of value :

const ids=[525354,123,131415];

I want to set checked to true if id matched. My main array may go to 6 to 7 step deep.

What I've done till yet :

setCheckedFlagToItems(checkList, items) {
        return items.map((item) => {
            const node = item;
            if (checkList.indexOf(node.id) !== -1) {
                node.checked = true;
            }
            if ((node.children) && (Array.isArray(node.children) && node.children.length > 0)) {
                this.setCheckedFlagToItems(checkList, node.children);
            }
            return node;
        }, this);
    }

But it not working as usual.

This is my actual array :

let mainArray= [
    {
        value: '/AG_TURF-123',
        label: 'Ag & Turf',
        checked: false,
        id:123,
        children: [
            {
                value: '/AG_TURF-123/TRACTOR-456',
                label: 'Tractors',
                checked: false,
                id:456,
                children: [
                    {
                        value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series',
                        label: 'Large (7, 8, 9) Series',
                        checked: false,
                        id:789,
                        children: [{
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor',
                            label: '7 Family Tractor',
                            checked: false,
                            id:101112
                        },{
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor',
                            label: '8 Family Tractor',
                            checked: false,
                            id:131415
                        },{
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor',
                            label: '9 Family Tractor',
                            checked: false,
                            id:161718
                        }],
                    },
                    {
                        value: '/app/Http/routes.js',
                        label: 'routes.js',
                        checked: false,
                        id:181920
                    },
                ],
            },
            {
                value: '/app/Providers',
                label: 'Providers',
                checked: false,
                id:212223,
                children: [{
                    value: '/app/Http/Providers/EventServiceProvider.js',
                    label: 'EventServiceProvider.js',
                    checked: false,
                    id:242526
                }],
            },
        ],
    },
    {
        value: '/config',
        label: 'config',
        checked: false,
        id:272829,
        children: [
            {
                value: '/config/app.js',
                label: 'app.js',
                checked: false,
                id:303132
            },
            {
                value: '/config/database.js',
                label: 'database.js',
                checked: false,
                id:333435
            },
        ],
    },
    {
        value: '/public',
        label: 'public',
        checked: false,
        id:353637,
        children: [
            {
                value: '/public/assets/',
                label: 'assets',
                checked: false,
                id:383940,
                children: [{
                    value: '/public/assets/style.css',
                    label: 'style.css',checked: false,
                    id:404142
                }],
            },
            {
                value: '/public/index.html',
                label: 'index.html',
                checked: false,
                id: 434445
            },
        ],
    },
    {
        value: '/.env',
        label: '.env',
        checked: false,
        id: 464748
    },
    {
        value: '/.gitignore',
        label: '.gitignore',
        checked: false,
        id: 495051
    },
    {
        value: '/README.md',
        label: 'README.md',
        checked: false,
        id: 525354
    },
];

This is my list of value :

const ids=[525354,123,131415];

I want to set checked to true if id matched. My main array may go to 6 to 7 step deep.

What I've done till yet :

setCheckedFlagToItems(checkList, items) {
        return items.map((item) => {
            const node = item;
            if (checkList.indexOf(node.id) !== -1) {
                node.checked = true;
            }
            if ((node.children) && (Array.isArray(node.children) && node.children.length > 0)) {
                this.setCheckedFlagToItems(checkList, node.children);
            }
            return node;
        }, this);
    }

But it not working as usual.

Share Improve this question asked Apr 25, 2017 at 13:27 Hashir HussainHashir Hussain 6824 gold badges9 silver badges28 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 15

You could use an iterative and recursice approach with a named function as callback for Array#forEach.

let mainArray = [
{
    value: '/AG_TURF-123', 
    label: 'Ag & Turf', 
    checked: false, 
    id: 123, 
    children: [
        { 
            value: '/AG_TURF-123/TRACTOR-456', 
            label: 'Tractors', 
            checked: false, 
            id: 456, 
            children: [
                { 
                    value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series', 
                    label: 'Large (7, 8, 9) Series', 
                    checked: false, 
                    id: 789, 
                    children: [
                        { 
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor', 
                            label: '7 Family Tractor', 
                            checked: false, 
                            id: 101112 
                        }, 
                        { 
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor', 
                            label: '8 Family Tractor', 
                            checked: false, 
                            id: 131415 
                        }, 
                        { 
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor', 
                            label: '9 Family Tractor', 
                            checked: false, 
                            id: 161718 
                        }
                    ] 
                }, 
                {
                    value: '/app/Http/routes.js', 
                    label: 'routes.js', 
                    checked: false, 
                    id: 181920 
                }
            ]
        }, 
        { 
            value: '/app/Providers', 
            label: 'Providers', 
            checked: false, 
            id: 212223, 
            children: [
                { 
                    value: '/app/Http/Providers/EventServiceProvider.js', 
                    label: 'EventServiceProvider.js', 
                    checked: false, 
                    id: 242526 
                }
            ]
        }
    ]
}, 
{
    value: '/config', 
    label: 'config', 
    checked: false, 
    id: 272829, 
    children: [
        {
            value: '/config/app.js', 
            label: 'app.js', 
            checked: false, 
            id: 303132
        },
        {
            value: '/config/database.js', 
            label: 'database.js', 
            checked: false, 
            id: 333435 
        }
    ]
}, 
{
    value: '/public', 
    label: 'public', 
    checked: false, 
    id: 353637, 
    children: [
        {
            value: '/public/assets/', 
            label: 'assets', 
            checked: false, 
            id: 383940, 
            children: [
                {
                    value: '/public/assets/style.css', 
                    label: 'style.css', 
                    checked: false, 
                    id: 404142
                }
            ]
        }, 
        {
            value: '/public/index.html', 
            label: 'index.html', 
            checked: false, 
            id: 434445 
        }
    ] 
}, 
{ 
    value: '/.env', 
    label: '.env', 
    checked: false, 
    id: 464748 
}, 
{ 
    value: '/.gitignore', 
    label: '.gitignore', 
    checked: false, 
    id: 495051 
}, 
{ 
    value: '/README.md', 
    label: 'README.md', 
    checked: false, 
    id: 525354 
}
],
    ids = [525354, 123, 131415];

mainArray
    .forEach(
        function iter(a) {
            if (ids.includes(a.id)) {
                a.checked = true;
            }
            Array.isArray(a.children) && a.children.forEach(iter);
        }
    );

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

If your ids are "unique" (there's only one unique object for each id property), you could also split this action in to two steps:

  1. Make a new data structure that flattens all items in to one object of id: item
  2. Loop through the ids to retrieve the items from this object.

If you find yourself looking up many objects by id, it might be easier to create this interim representation.

The creation of the map uses recursion similar to the other answer: whenever an item contains a children array, it adds those to the map object before it returns.

const mainArray = [{ value: '/AG_TURF-123', label: 'Ag & Turf', checked: false, id: 123, children: [{ value: '/AG_TURF-123/TRACTOR-456', label: 'Tractors', checked: false, id: 456, children: [{ value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series', label: 'Large (7, 8, 9) Series', checked: false, id: 789, children: [{ value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor', label: '7 Family Tractor', checked: false, id: 101112 }, { value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor', label: '8 Family Tractor', checked: false, id: 131415 }, { value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor', label: '9 Family Tractor', checked: false, id: 161718 }] }, { value: '/app/Http/routes.js', label: 'routes.js', checked: false, id: 181920 }] }, { value: '/app/Providers', label: 'Providers', checked: false, id: 212223, children: [{ value: '/app/Http/Providers/EventServiceProvider.js', label: 'EventServiceProvider.js', checked: false, id: 242526 }] }] }, { value: '/config', label: 'config', checked: false, id: 272829, children: [{ value: '/config/app.js', label: 'app.js', checked: false, id: 303132 }, { value: '/config/database.js', label: 'database.js', checked: false, id: 333435 }] }, { value: '/public', label: 'public', checked: false, id: 353637, children: [{ value: '/public/assets/', label: 'assets', checked: false, id: 383940, children: [{ value: '/public/assets/style.css', label: 'style.css', checked: false, id: 404142 }] }, { value: '/public/index.html', label: 'index.html', checked: false, id: 434445 }] }, { value: '/.env', label: '.env', checked: false, id: 464748 }, { value: '/.gitignore', label: '.gitignore', checked: false, id: 495051 }, { value: '/README.md', label: 'README.md', checked: false, id: 525354 }];

// We reduce the array of nested items in to one object of:
// { id: item }
const idMap = mainArray.reduce(function merge(map, node) {
  map[node.id] = node;
  
  if (Array.isArray(node.children)) {
    node.children.reduce(merge, map);
  }
  
  return map;
}, {});

const ids = [525354, 123, 131415];

// Whenever you need an item, you can get it
// using idMap[id]
const items = ids.map(id => idMap[id]);
items.forEach(item => item.checked = true);

// or: ids.forEach(id => idMap[id].checked = true)

发布评论

评论列表(0)

  1. 暂无评论