Преобразование вложенного массива в объект, сопоставление индекса массива с идентификатором объекта - PullRequest
0 голосов
/ 19 января 2019

В настоящее время я борюсь с редукторным редуктором.

//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));

У меня кончились идеи, как это реализовать.UNUSED и UNKNOWN также должны быть отфильтрованы.Так что конечный результат в этом примере просто будет как в const expectedFinalResult.В настоящее время const result возвращает неверный результат.

Надеюсь, у кого-то есть идея получше или лучше.

Спасибо

Ответы [ 2 ]

0 голосов
/ 19 января 2019

Вы можете сделать это с помощью Reduce:

Object.entries(response.data.results)
    .reduce((acc, [key, { items }]) => ({
        ...acc,
        [key]: { // we can use the dynamic keys to add in our accumulated object
            items: items
                .map(itemId => stateItems.find(x => x.id === itemId)) // you can use find directly instead of findIndex then access
                .filter(Boolean) // we skip the unneeded elements
        }
    }), {});
0 голосов
/ 19 января 2019

Вы на правильном пути с 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))
    };
}

Live Пример:

//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 действительно, действительно, действительно, очень большой (например, сотни тысяч), может быть целесообразно вместо этого сделать Map из stateItem с id:

// 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))
    };
}

Live Пример:

//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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...