#javascript #node.js #arrays
#javascript #node.js #массивы
Вопрос:
пример req.files из multer.js
[
{
fieldname: files0,
originalname: 'Screenshot from 2020-05-23 01-52-30.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
filename: '1606822252923_Screenshot from 2020-05-23 01-52-30.png',
path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252923_Screenshot from 2020-05-23 01-52-30.png',
size: 172092
},
{
fieldname: files0,
originalname: 'Screenshot from 2020-05-22 08-44-05.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
filename: '1606822252925_Screenshot from 2020-05-22 08-44-05.png',
path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252925_Screenshot from 2020-05-22 08-44-05.png',
size: 440592
},
{
fieldname: files1,
originalname: 'Screenshot from 2020-05-30 11-36-42.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
filename: '1606822252930_Screenshot from 2020-05-30 11-36-42.png',
path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252930_Screenshot from 2020-05-30 11-36-42.png',
size: 477511
},
{
fieldname: files1,
originalname: 'Screenshot from 2020-05-30 11-36-36.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
filename: '1606822252931_Screenshot from 2020-05-30 11-36-36.png',
path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252931_Screenshot from 2020-05-30 11-36-36.png',
size: 223362
},
{
fieldname: files1,
originalname: 'Screenshot from 2020-05-30 11-36-31.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
filename: '1606822252932_Screenshot from 2020-05-30 11-36-31.png',
path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252932_Screenshot from 2020-05-30 11-36-31.png',
size: 260419
}
]
Я хочу динамически группировать каждый объект JSON с их именем поля и сохранять их в массиве объектов, используя их номер имени поля в качестве индекса массива.
Группы могут быть от 0 до 9, в зависимости от пользовательского ввода.
Результат, на который я надеюсь, это что-то вроде
someArr = [
[
{
fieldname: files0
originalname: somevalue,
...
size: some value
},
{
fieldname: files0,
originalname: somevalue,
...
size: some value
},
]
,
[
{
fieldname: files1,
originalname: somevalue,
...
size: some value
},
{
fieldname: files1,
originalname: somevalue,
...
size: some value
},
{
fieldname: files1,
originalname: somevalue,
...
size: some value
},
]
...
]
и если он существует, someArr[9] вернет
[
{
fieldname: files9,
originalname: somevalue,
...
size: some value
},
{
fieldname: files9,
originalname: somevalue,
...
size: some value
},
]
То, что я попробовал, — это сначала проанализировать целые числа из имен полей и переназначить их как свои значения для лучшей сортировки с помощью for-циклов
Object.keys(req.files).forEach((key) => {
const thisFile = req.files[key];
const thisFileGroup = parseInt(thisFile.fieldname.match(/d/g).join(''), 10);
// rename fieldname from files0, files1 ... to 0 , 1 ....
req.files[key].fieldname = thisFileGroup;
});
Но отсюда я не могу найти, куда поместить этот элемент (thisFile), поскольку я не могу предварительно указать каждый массив в верхней области видимости, поскольку они также должны создаваться динамически.
Комментарии:
1. Пожалуйста, примите ответ @mplungjan. Я пропустил, что вам нужно упорядочивать по индексу
0
и1
т. Д. Использование object отлично подходит для группировки, но окончательный порядок не будет упорядочен по алфавитному порядку ключей.2. @Roko C. Buljan проверено! Я обязательно также буду иметь в виду ваше решение!
Ответ №1:
Я бы использовал сокращение
const data = [
{ fieldname: 'files0', originalname: 'Screenshot from 2020-05-23 01-52-30.png', },
{ fieldname: 'files0', originalname: 'Screenshot from 2020-05-22 08-44-05.png', },
{ fieldname: 'files1', originalname: 'Screenshot from 2020-05-30 11-36-42.png', },
{ fieldname: 'files1', originalname: 'Screenshot from 2020-05-30 11-36-36.png', },
{ fieldname: 'files1', originalname: 'Screenshot from 2020-05-30 11-36-31.png', }],
arr = data.reduce((acc, cur) => {
const idx = cur.fieldname.replace("files",""); // get 0, 1
if (acc[idx]) acc[idx].push(cur); // if already there, just push
else acc[idx] = [cur]; // otherwise initialise
return acc;
},[])
console.log(arr)
ПРИМЕЧАНИЕ: группы могут быть от 0 до 9, в зависимости от пользовательского ввода.
Я предполагаю, что дыр нет, поскольку это может привести к разреженному массиву, поэтому
data = [
{ fieldname : 'files0' },
{ fieldname : 'files0' },
{ fieldname : 'files3' },
{ fieldname : 'files3' },
}
создало бы массив
[
[ { fieldname : 'files0' }, { fieldname : 'files0' } ],
null,
null,
[ { fieldname : 'files3' }, { fieldname : 'files3' } ],
]
Комментарии:
1. чисто и просто!! отличный ответ!! Я должен искать reduce
2. @mplungjan да, понял! Нет fieldname
replace
-ing! да! : P 😉3. Единственная проблема, которую я вижу в своем коде, — это null, если есть
filesx
или files0,1,34. @viviet Я думаю, что это тот ответ, который вам нужен, используя объекты (как я и предлагал), вы потеряете порядок индексов групп!
5. @mplungjan извиняюсь, я полностью пропустил в вопросе OP «порядок по индексу» . 1
Ответ №2:
Если вам не нужен обязательно порядок по индексу files[index]
в этом случае вы могли бы преобразовать Array.prototype.reduce() в Object.
Ваш объект будет сгруппирован по fieldname
свойствам (хотя и не в алфавитном порядке), содержащим один массив с элементами, имеющими тот же ключ свойства.
Выполните итерацию вашего объекта, используя Object.values() (и Array.prototype.forEach(), если это необходимо).
const data = [
{ fieldname: "files0", originalname: '0-a'},
{ fieldname: "files0", originalname: '0-b'},
{ fieldname: "files1", originalname: '1-a'},
{ fieldname: "files1", originalname: '1-b'},
{ fieldname: "files1", originalname: '1-c'},
];
const byFieldName = data.reduce((ob, d) => {
if (!ob.hasOwnProperty(d.fieldname)) ob[d.fieldname] = [];
ob[d.fieldname].push(d);
return ob;
}, {});
// console.log(byFieldName); // Uncomment to see how it looks like
console.log( Object.values(byFieldName) );
Комментарии:
1. Этот код сначала уменьшает, а затем принимает значения объекта, чтобы избавиться от ключа byFieldName — это неэффективно — это безопаснее, чем полагаться на цифру в ключе, но если это гарантировано, то мой код более эффективен
2. Это упорядочит конечный массив по порядку, в котором значения fieldname встречаются во входном массиве. Вам нужно будет отсортировать исходный массив по имени поля, прежде чем сокращать его с помощью этого подхода.
3. Объект или массив — это данные. Вы @mplungjan можете игнорировать второй журнал консоли и рассматривать этот ответ так, как если бы первый был раскомментирован. Вы все равно будете зацикливать данные, если вам нужно получить значения. Лучшая часть в том, чтобы иметь его в качестве структурированного объекта, заключается в том, что вы можете — при необходимости — напрямую использовать весь массив, используя его ключ:
const fn1 = byFieldName["files0"]
при использовании массива вам необходимо получить доступ к глубоким слоям и выполнить их итерацию, чтобы каждый.some()
из элементов соответствовал желаемому ключу.4. Порядок свойств объектов @pilchard предсказуем в JavaScript ES2015 — после этого цикл не имеет разницы в вводе.
5. пилчард да, я знаю, но в этом предложении нет необходимости (то есть просто группировать их и пользоваться преимуществами — жестко, а не в алфавитном порядке ) дополнительные итерации могут быть слишком дорогими для чего-то, что @mplungjan уже решил. — И PS, я пропустил в вопросе необходимость упорядочивания OP по индексу .
Ответ №3:
Я стараюсь не изменять вашу логику, чтобы сделать это.
если нет files2
, то filesArray[2] будет undefined
.
// Omit other fields
const req = {
files: [
{ fieldname: "files0", originalname: 'Screenshot from 2020-05-23 01-52-30.png'},
{ fieldname: "files0", originalname: 'Screenshot from 2020-05-22 08-44-05.png'},
{ fieldname: "files1", originalname: 'Screenshot from 2020-05-30 11-36-42.png'},
{ fieldname: "files1", originalname: 'Screenshot from 2020-05-30 11-36-36.png'},
{ fieldname: "files1", originalname: 'Screenshot from 2020-05-30 11-36-31.png'},
{ fieldname: "files3", originalname: 'Screenshot from 2020-05-30 11-36-42.png'},
{ fieldname: "files3", originalname: 'Screenshot from 2020-05-30 11-36-36.png'},
{ fieldname: "files3", originalname: 'Screenshot from 2020-05-30 11-36-31.png'}
]
}
let filesArray = []
for (let file of req.files) {
const thisFileGroup = parseInt(file.fieldname.match(/d/g).join(''), 10);
if (!filesArray[thisFileGroup]) {
filesArray[thisFileGroup] = []
}
filesArray[thisFileGroup].push(file)
}
console.log(filesArray[2]) // will be undefined
console.log(filesArray[1]) // will be files1 array
console.log(filesArray)