javascript - 将嵌套数组转换为对象,将数组索引与对象 ID 匹配

标签 javascript node.js reactjs redux

我目前正在与 redux reducer 作斗争。

//backend response
const response = {
    data: {
        results: {
            222: {
                items: ['id1', 'id3']
            },
            333: {
                items: ['id2', 'id4', 'id999 (UNKNOWN)']
            }
        }
    }
};

//currently saved in redux state
const stateItems = [
    {
        id: 'id1',
        name: 'item ONE'
    }, {
        id: 'id2',
        name: 'item TWO'
    }, {
        id: 'id3',
        name: 'item THREE'
    }, {
        id: 'id4',
        name: 'item FOUR'
    }, {
        id: 'id5',
        name: 'item FIVE (UNUSED)'
    }, {
        id: 'id6',
        name: 'item SIX (UNUSED)'
    }
];


//converting items: ['ids'] => items: [{id: 'id', name: 'itemName'}]
const result = Object.values(response.data.results).map((keys, index, array) => {
    keys.items = keys.items.map(itemId => {
        return stateItems[stateItems.findIndex(x => x.id === itemId)];
    });

    return response.data.results;
});


//final result should be:
const expectedFinalResult = {
    222: {items: [{id: 'id1', name: 'item ONE'}, {id: 'id3', name: 'item THREE'}]},
    333: {items: [{id: 'id2', name: 'item TWO'}, {id: 'id4', name: 'item FOUR'}]}
};

//both should be equal:
console.log(JSON.stringify(expectedFinalResult));
console.log(JSON.stringify(result));
console.log('same result: ' + JSON.stringify(result) === JSON.stringify(expectedFinalResult));

我已经没有想法了,如何实现它。 UNUSEDUNKNOWN 也应该被过滤掉。因此本例中的最终结果就像 const ExpectedFinalResult 中的那样。目前,const result 返回错误结果。

希望有人有更好的想法或更好的方法。

谢谢

最佳答案

Object.entries 的方向是正确的。您可以使用解构来挑选键('222''333')和值对象的 items 数组,然后使用该数组过滤 stateItems 并为结果中的每个条目生成 items 数组:

const result = {};
for (const [key, {items}] of Object.entries(response.data.results)) {
    result[key] = {
        items: stateItems.filter(item => items.includes(item.id))
    };
}

实例:

//backend response
const response = {
    data: {
        results: {
            222: {
                items: ['id1', 'id3']
            },
            333: {
                items: ['id2', 'id4', 'id999 (UNKNOWN)']
            }
        }
    }
};

//currently saved in redux state
const stateItems = [
    {
        id: 'id1',
        name: 'item ONE'
    }, {
        id: 'id2',
        name: 'item TWO'
    }, {
        id: 'id3',
        name: 'item THREE'
    }, {
        id: 'id4',
        name: 'item FOUR'
    }, {
        id: 'id5',
        name: 'item FIVE (UNUSED)'
    }, {
        id: 'id6',
        name: 'item SIX (UNUSED)'
    }
];


const result = {};
for (const [key, {items}] of Object.entries(response.data.results)) {
    result[key] = {
        items: stateItems.filter(item => items.includes(item.id))
    };
}

//final result should be:
const expectedFinalResult = {
    222: {items: [{id: 'id1', name: 'item ONE'}, {id: 'id3', name: 'item THREE'}]},
    333: {items: [{id: 'id2', name: 'item TWO'}, {id: 'id4', name: 'item FOUR'}]}
};

//both should be equal:
console.log(JSON.stringify(result, null, 4));
.as-console-wrapper {
  max-height: 100% !important;
}

这会多次遍历stateItems。如果它或 response.data.results 真的非常非常大(比如数十万),那么可能值得按 idstateItem 进行 Map 来代替:

// Create map of state items (only once each time stateItems changes):
const stateItemMap = new Map(stateItems.map(item => [item.id, item]));

// Map results (each time you get results):
const result = {};
for (const [key, {items}] of Object.entries(response.data.results)) {
    result[key] = {
        items: items.map(id => stateItemMap.get(id))
    };
}

实例:

//backend response
const response = {
    data: {
        results: {
            222: {
                items: ['id1', 'id3']
            },
            333: {
                items: ['id2', 'id4', 'id999 (UNKNOWN)']
            }
        }
    }
};

//currently saved in redux state
const stateItems = [
    {
        id: 'id1',
        name: 'item ONE'
    }, {
        id: 'id2',
        name: 'item TWO'
    }, {
        id: 'id3',
        name: 'item THREE'
    }, {
        id: 'id4',
        name: 'item FOUR'
    }, {
        id: 'id5',
        name: 'item FIVE (UNUSED)'
    }, {
        id: 'id6',
        name: 'item SIX (UNUSED)'
    }
];

// Create map of state items (only once each time stateItems changes):
const stateItemMap = new Map(stateItems.map(item => [item.id, item]));

// Map results (each time you get results):
const result = {};
for (const [key, {items}] of Object.entries(response.data.results)) {
    result[key] = {
        items: items.map(id => stateItemMap.get(id))
    };
}

//final result should be:
const expectedFinalResult = {
    222: {items: [{id: 'id1', name: 'item ONE'}, {id: 'id3', name: 'item THREE'}]},
    333: {items: [{id: 'id2', name: 'item TWO'}, {id: 'id4', name: 'item FOUR'}]}
};

//both should be equal:
console.log(JSON.stringify(result, null, 4));
.as-console-wrapper {
  max-height: 100% !important;
}

关于javascript - 将嵌套数组转换为对象,将数组索引与对象 ID 匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54269143/

相关文章:

mysql - 使用ssh隧道连接mysql不起作用

javascript - Selenium webdriver - 解决多个 promise

node.js - 生成 Joi 验证 Sequelize 模型

javascript - react native : Strange Issue With Updating State

javascript - 使用 YUI 3 格式化输入数据

javascript - 将jquery dataTables(带有CRUD功能)连接到mysql

reactjs - 替换 Query 对象的 my 字段时缓存数据可能会丢失

javascript - 使用 onClick 和 React AutoBind

javascript - 输入更改时不调用指令

javascript - 异步 IndexRoute 不加载 react 路由器