#javascript
Вопрос:
Я пытаюсь перенести результат запроса в матрицу. По сути, если бы у меня был такой результат:
Атрибут1 | Вэл | Рассчитывать |
---|---|---|
Яблоки | Вал 1 | 100 |
Бананы | Вал 1 | 200 |
Яблоки | Вал 2 | 300 |
Бананы | Вал 2 | 400 |
Я хочу перенести это на это:
Атрибут1 | Вал 1 | Вал 2 |
---|---|---|
Яблоки | 100 | 300 |
Бананы | 200 | 400 |
Однако количество значений в поле атрибута и поле Val являются динамическими. Как бы я, следовательно, перенес это в JS, чтобы мой выходной массив JSON представлял собой динамическую структуру, зависящую от результата запроса?
У меня есть фрагмент кода ниже, где я перечислил различные [Attribute1] и [Val], но как мне построить массив json, в котором определение является динамическим? Я сделал попытку в конце концов, но я знаю, что это еще не правильно…
var res = [{
"Attribute1": 'Apples',
"Val": 'Val 1',
"Count": 100
},
{
"Attribute1": 'Bananas',
"Val": 'Val 1',
"Count": 200
},
{
"Attribute1": 'Apples',
"Val": 'Val 2',
"Count": 300
},
{
"Attribute1": 'Bananas',
"Val": 'Val 2',
"Count": 400
}
]
const y_result = [];
const map = new Map();
for (const item of res) {
if (!map.has(item.Attribute1)) {
map.set(item.Attribute1, true); // set any value to Map
y_result.push({
Attribute1: item.Attribute1,
});
}
}
console.log(y_result)
const x_result = [];
const x_map = new Map();
for (const item of res) {
if (!x_map.has(item.Val)) {
x_map.set(item.Val, true); // set any value to Map
x_result.push({
Attribute1: item.Val,
});
}
}
console.log(x_result)
let tmp
let new_res
console.log(y_result[0].Attribute1)
for (const item of y_result) {
tmp = { y_result[0].Attribute1 : item.Count };
new_res.push(tmp)
}
console.log(new_res)
Комментарии:
1. вау, еще 2 отличных ответа, пока я писал свой 🙂 голосую за оба! 🙂
Ответ №1:
таким образом..
const res =
[ { Attribute1: 'Apples', Val: 'Val 1', Count: 100 }
, { Attribute1: 'Bananas', Val: 'Val 1', Count: 200 }
, { Attribute1: 'Apples', Val: 'Val 2', Count: 300 }
, { Attribute1: 'Bananas', Val: 'Val 2', Count: 400 }
]
const y_result = Object.entries(res.reduce((a,{Attribute1,Val,Count})=>
{
a[Attribute1] = a[Attribute1] ?? {}
a[Attribute1][Val] = Count
return a
},{})).map(([Attribute1,vals])=>({Attribute1, ...vals}))
console.log( y_result )
.as-console-wrapper { max-height: 100% !important; top: 0 }
Комментарии:
1. Мило! Мой подход состоял в том, чтобы использовать глобальную переменную, вы избегаете этого, создавая объект, а затем
map
записываете его записи в массив, любите его.
Ответ №2:
Мой подход, используя некоторые destructuring
, и. Array#forEach
- Просмотрите каждый элемент в массиве
- Проверьте его
Attribute1
значение и проверьте, видели ли его раньше. - Если он прочитал
Val
свойство, добавьте его в существующий объект - Если объект не создан, прочитайте
Val
свойство и установите его.
Код:
var res = [
{ Attribute1: "Apples", Val: "Val 1", Count: 100 },
{ Attribute1: "Bananas", Val: "Val 1", Count: 200 },
{ Attribute1: "Apples", Val: "Val 2", Count: 300 },
{ Attribute1: "Bananas", Val: "Val 2", Count: 400 },
];
let result = [], seenBefore = [];
res.forEach(({ Attribute1, Count, Val }) => {
let foundHere = seenBefore.indexOf(Attribute1)
if (foundHere !== -1){
result[foundHere][Val] = Count;
}
else {
result.push({ Attribute1, [Val]: Count });
seenBefore.push(Attribute1)
}
})
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0}
Комментарии:
1. Совсем неплохо 🙂
2. Спасибо вам за вашу помощь — тоже хороший подход.
Ответ №3:
Это то, что вы ищете?
Приведенный ниже фрагмент выполняет эту работу в 2 этапа: сначала значение Val
становится ключом и принимает значение Count
как свое собственное значение, а затем объединяет все значения вместе. Второй шаг выполняется с помощью registry
объекта, который позволяет добавить все ключи, которых нет Attribute1
, в уже существующую запись, если она была предварительно записана там.
const res = [
{
Attribute1: 'Apples',
Val: 'Val 1',
Count: 100,
},
{
Attribute1: 'Bananas',
Val: 'Val 1',
Count: 200,
},
{
Attribute1: 'Apples',
Val: 'Val 2',
Count: 300,
},
{
Attribute1: 'Bananas',
Val: 'Val 2',
Count: 400,
},
];
const registry = {};
const result = res
.map(
({ Attribute1, Val, Count }) => ({
Attribute1,
[Val]: Count,
}),
[]
)
.reduce((acc, row, i) => {
const at = row.Attribute1;
if (!(at in registry)) {
registry[at] = i;
acc.push(row);
return acc;
}
Object.entries(row).forEach(([key, value]) => {
if (key !== 'Attribute1') {
acc[registry[at]][key] = value;
}
});
return acc;
}, []);
console.log(result);