Cómo filtrar una matriz que tiene tipos de datos mixtos

Resuelto volume one asked hace 9 meses • 2 respuestas

Tengo una matriz que es así:

const AllFiles = [

    {name: "ExistingFile1", mimetype: "image/jpg", size: "500"},

    [ 
     File, // This is the New File itself (see File API)
     {name: "NewFile1", mimetype: "video/mp4", size: "9000"}
    ],

    {name: "ExistingFile2", mimetype: "video/mp4", size: "4000"},

    [ 
     File, // This is the New File itself (see File API)
     {name: "NewFile2", mimetype: "image/jpg", size: "500"}
    ],

 ]

Como puede ver, la AllFilesmatriz contiene una combinación de objetos y matrices.

Necesito filtrar la AllFilesmatriz para devolver solo elementos donde mimetypecomienza "image/".

Entonces comencé con lo siguiente:

const FilteredFiles = AllFiles.filter((FileItem, index) => FileItem.mimetype.startsWith("image/"))

El problema es que sólo busca dónde mimetypeestá en un objeto de nivel superior. No profundiza en dónde un archivo nuevo tiene mimetypeun objeto de segundo nivel dentro de una matriz.

Para obtener los mimetypearchivos existentes, debe utilizar:FileItem[0].mimetype

Pero para obtener mimetypearchivos nuevos necesitas usar:FileItem[0][1].mimetype

Debido a esta discrepancia, no puedo filtrar la AllFilesmatriz. ¿Cómo podría lograrse esto?

volume one avatar Feb 16 '24 23:02 volume one
Aceptado

Puede utilizar un ??operador para tener una solución muy compacta:

const AllFiles = [{name:"ExistingFile1",mimetype:"image/jpg",size:"500"},["FILE",{name:"NewFile1",mimetype:"video/mp4",size:"9000"}],{name:"ExistingFile2",mimetype:"video/mp4",size:"4000"},["FILE",{name:"NewFile2",mimetype:"image/jpg",size:"500"}]];
 
const result = AllFiles.filter(f => (f[1] ?? f).mimetype.startsWith('image'));

result.forEach(r => console.log(JSON.stringify(r)));
Expandir fragmento

Alexander Nenashev avatar Feb 16 '2024 17:02 Alexander Nenashev

Un enfoque sencillo sería comprobar si la entidad en la iteración tiene la mimetypepropiedad. Si es así, puedes leerlo directamente. Si no es así, puede asumir que es una matriz y, en su lugar, debe leer desde la segunda entidad de la matriz.

const File = "foo", AllFiles = [{name:"ExistingFile1",mimetype:"image/jpg",size:"500"},["foo",{name:"NewFile1",mimetype:"video/mp4",size:"9000"}],{name:"ExistingFile2",mimetype:"video/mp4",size:"4000"},["foo",{name:"NewFile2",mimetype:"image/jpg",size:"500"}]];

const filteredFiles = AllFiles.filter(entity => {
  const obj = entity.hasOwnProperty('mimetype') ? entity : entity[1];
  return obj.mimetype.startsWith("image/");
});

console.log(filteredFiles);
Expandir fragmento

Tenga en cuenta que esto es sólo para fines de demostración. En un sistema de producción, sugeriría algunas comprobaciones más para que esto sea más sólido, como verificar que los tipos de datos sean los esperados, pero el ejemplo anterior es la versión simplista del patrón a seguir.

Rory McCrossan avatar Feb 16 '2024 17:02 Rory McCrossan