Группировать значение ключа из плоской базы данных только по ключевым частям

#javascript #arrays #sorting #object #lodash

#javascript #массивы #сортировка #объект #Lodash

Вопрос:

Я получаю некоторые данные из плоской базы данных следующим образом:

 [{
        key: "user_15478",
        value: "xxx"
    }, {
        key: "user_name_15478",
        value: "xxx"
    }, {
        key: "user_age_15478",
        value: 5
    }, {
        key: "user_24547",
        value: "xxx"
    }, {
        key: "user_name_24547",
        value: "xxx"
    }, {
        key: "user_age_24547",
        value: 12
    }, {
        key: "user_42412",
        value: "xxx"
    }, {
        key: "user_name_42412",
        value: "xxx"
    }, {
        key: "user_age_42412",
        value: 42
    }
]
  

Что было бы проще, в vanila js или с помощью библиотеки Lodash преобразовать его, сгруппировав по цифре в ключе (15478, 24547 и т.д.).

Например:

 [{
        15478: [{
                key: "user_15478",
                value: "xxx"
            }, {
                key: "user_name_15478",
                value: "xxx"
            }, {
                key: "user_age_15478",
                value: 5
            }
        ]
    }, {
        24547: [{
                key: "user_24547",
                value: "xxx"
            }, {
                key: "user_name_24547",
                value: "xxx"
            }, {
                key: "user_age_24547",
                value: 12
            }
        ]
    }, {
        42412: { {
                key: "user_42412",
                value: "xxx"
            }, {
                key: "user_name_42412",
                value: "xxx"
            }, {
                key: "user_age_42412",
                value: 42
            }
            ]
        }
        ]
  

Заранее спасибо за помощь.

Ответ №1:

Вы можете использовать reduce и внутри функции обратного вызова проверить использование lastIndexOf , чтобы получить последнее _ . Затем проверьте объект accumulator, существует ли какой-либо ключ, который совпадает с номером. Если нет, то создайте ключ и добавьте к нему значение.

 let data = [{
    key: "user_15478",
    value: "xxx"
  },
  {
    key: "user_name_15478",
    value: "xxx"
  },
  {
    key: "user_age_15478",
    value: 5
  },
  {
    key: "user_24547",
    value: "xxx"
  },
  {
    key: "user_name_24547",
    value: "xxx"
  },
  {
    key: "user_age_24547",
    value: 12
  },
  {
    key: "user_42412",
    value: "xxx"
  },
  {
    key: "user_name_42412",
    value: "xxx"
  },
  {
    key: "user_age_42412",
    value: 42
  }
];

let newData = data.reduce((acc, curr) => {
  const _key = curr.key;
  const getNum = _key.substr(_key.lastIndexOf('_')   1, _key.length);
  if (!acc[getNum]) {
    acc[getNum] = []
  }
  acc[getNum].push(curr)
  return acc;
}, {});
console.log([newData])  

Комментарии:

1. Большое спасибо за очень быстрый ответ, я действительно думаю, что моя структура данных немного отличается от приведенного мной примера, потому что, когда я пробую ваш код на своих данных, я получаю data.reduce — это не функция, на примере данных это работает. Вот две структуры данных (оригинал и пример): pasteboard.co/JnevTJp.jpg

2. Хорошо, я нашел решение, мои данные — это объект, поэтому я просто обернул его Object.values (данные), например: пусть newData = Object.values(данные).reduce((acc, curr) => { и т.д… Работает отлично, большое спасибо!

Ответ №2:

Если ваш входной массив не отсортирован, то сначала вам нужно отсортировать его на основе key . Итак, после сортировки это будет выглядеть следующим образом:

 [{key: "user_15478",
 value: "xxx"
 },
{key: "user_24547",
 value: "xxx"
 },
.... //then _age wise
{key: "user_age_42412",
 value: "xxx"
 },
... //then _name wise 
{key: "user_name_42412",
 value: "xxx"
 },
]

  

а затем просто продолжайте передавать объекты в накопитель, используя reduce

 let arr= [ { key: "user_15478", value: "xxx" }, { key: "user_name_15478", value: "xxx" }, { key: "user_age_15478", value: 5 }, { key: "user_24547", value: "xxx" }, { key: "user_name_24547", value: "xxx" }, { key: "user_age_24547", value: 12 }, { key: "user_42412", value: "xxx" }, { key: "user_name_42412", value: "xxx" }, { key: "user_age_42412", value: 42 }, ];

arr = arr.sort((a, b) => a.key > b.key ? 1 : -1)

let result=arr.reduce((acc, val) => {
  let field = val.key.split("_")
  if (field.length === 2) {
    acc[field[1]] = [{ ...val
    }]
  }
  else
  acc[field[2]].push(val)
  return acc;
}, {})
let wrappedResult=Object.keys(result).map(key=>({[key]:result[key]}))
console.log(wrappedResult)  

Ответ №3:

Вот решение с использованием Array.reduce()

 const transformed = data.reduce((acc, user) => {
    const [ key ] = user.key.match(/d $/);
    if (!(key in acc)) {
        acc[ key] = [];
    }
    acc[ key].push(user);
    return acc;
}, {});
  

Дано data такое:

 [{
    key: "user_15478",
    value: "xxx"
}, {
    key: "user_name_15478",
    value: "xxx"
}, {
    key: "user_age_15478",
    value: 5
}, {
    key: "user_24547",
    value: "xxx"
}, {
    key: "user_name_24547",
    value: "xxx"
}, {
    key: "user_age_24547",
    value: 12
}, {
    key: "user_42412",
    value: "xxx"
}, {
    key: "user_name_42412",
    value: "xxx"
}, {
    key: "user_age_42412",
    value: 42
}];