Home > Enterprise >  How to group files in array of objects deponds on the number of pages of each one
How to group files in array of objects deponds on the number of pages of each one

Time:08-10

I've got an array of objects:
Input

[
  { file: '1.pdf', text: 'Page: 1 / 2' },
  { file: '2.pdf', text: 'Page: 2 / 2' },
    // -- '1.pdf':['1.pdf','2.pdf']
  { file: '3.pdf', text: 'Page: 1 / 3' },
  { file: '4.pdf', text: 'Page: 2 / 3' },
  { file: '5.pdf', text: 'Page: 3 / 3' },
    // -- '2.pdf':['3.pdf','4.pdf', '5.pdf']
  { file: '6.pdf', text: 'Page: 1 / 4' },
  { file: '7.pdf', text: 'Page: 2 / 4' },
  { file: '8.pdf', text: 'Page: 3 / 4' },
  { file: '9.pdf', text: 'Page: 4 / 4' }
    // -- '3.pdf':['6.pdf','7.pdf', '8.pdf', '9.pdf']
]

And I wanna group them deponds on the number of pages of each one like this Output:

{
  "1.pdf": ["1.pdf", "2.pdf"],
  "2.pdf": ["3.pdf", "4.pdf", "5.pdf"],
  "3.pdf": ["6.pdf", "7.pdf", "8.pdf", "9.pdf"],
};

My Attempt:

let arr = [
  { file: "1.pdf", text: "Page: 1 / 2" },
  { file: "2.pdf", text: "Page: 2 / 2" },
  { file: "3.pdf", text: "Page: 1 / 3" },
  { file: "4.pdf", text: "Page: 2 / 3" },
  { file: "5.pdf", text: "Page: 3 / 3" },
  { file: "6.pdf", text: "Page: 1 / 4" },
  { file: "7.pdf", text: "Page: 2 / 4" },
  { file: "8.pdf", text: "Page: 3 / 4" },
  { file: "9.pdf", text: "Page: 4 / 4" },
];
let result = {};
let i = 0;
let x = null;
let visited = [];
for (const { file, text } of arr) {
  let val = text.split("/").at(-1).trim();
  let key = null;
  if (!visited.includes(val)) {
    key =   i   ".pdf";
    x = key;
    visited.push(val);
  } else {
    key = x;
  }
  result[key] ??= [];
  result[key].push(file);
}

console.log(result);

This works well in case where there's unique number of pages, BUT When there's the same number of pages on other it fails and combines them all to one instead of create new one:

[
  { file: '1.pdf', text: 'Page: 1 / 2' },
  { file: '2.pdf', text: 'Page: 2 / 2' },
  { file: '3.pdf', text: 'Page: 1 / 3' },
  { file: '4.pdf', text: 'Page: 2 / 3' },
  { file: '5.pdf', text: 'Page: 3 / 3' },
  { file: '6.pdf', text: 'Page: 1 / 4' },
  { file: '7.pdf', text: 'Page: 2 / 4' },
  { file: '8.pdf', text: 'Page: 3 / 4' },
  { file: '9.pdf', text: 'Page: 4 / 4' },
  { file: '10.pdf', text: 'Page: 1 / 2' },
  { file: '11.pdf', text: 'Page: 2 / 2' },
]

Output:

{
  "1.pdf": ["1.pdf", "2.pdf"],
  "2.pdf": ["3.pdf", "4.pdf", "5.pdf"], //      vvvvvvvvvvvvvvvvvv
  "3.pdf": ["6.pdf", "7.pdf", "8.pdf", "9.pdf", "10.pdf", "11.pdf"],
};

Expected Output:

{
  "1.pdf": ["1.pdf", "2.pdf"],
  "2.pdf": ["3.pdf", "4.pdf", "5.pdf"],
  "3.pdf": ["6.pdf", "7.pdf", "8.pdf", "9.pdf"],
  "4.pdf": ["10.pdf", "11.pdf"],
};

CodePudding user response:

CODE

var array = [
  { file: '1.pdf', text: 'Page: 1 / 2' },
  { file: '2.pdf', text: 'Page: 2 / 2' },
  { file: '3.pdf', text: 'Page: 1 / 3' },
  { file: '4.pdf', text: 'Page: 2 / 3' },
  { file: '5.pdf', text: 'Page: 3 / 3' },
  { file: '6.pdf', text: 'Page: 1 / 4' },
  { file: '7.pdf', text: 'Page: 2 / 4' },
  { file: '8.pdf', text: 'Page: 3 / 4' },
  { file: '9.pdf', text: 'Page: 4 / 4' },
  { file: '10.pdf', text: 'Page: 1 / 2' },
  { file: '11.pdf', text: 'Page: 2 / 2' },
];

var ret = {};
var lastGroup = 0;

array.forEach(function (value, i) {
    if(value.text.includes("Page: 1 /")){
        lastGroup  ;
        ret[lastGroup   ".pdf"]=[];
    }
    ret[lastGroup   ".pdf"].push(value.file);
});

console.log(ret);

OUTPUT

{
  "1.pdf": [
    "1.pdf",
    "2.pdf"
  ],
  "2.pdf": [
    "3.pdf",
    "4.pdf",
    "5.pdf"
  ],
  "3.pdf": [
    "6.pdf",
    "7.pdf",
    "8.pdf",
    "9.pdf"
  ],
  "4.pdf": [
    "10.pdf",
    "11.pdf"
  ]
}

CodePudding user response:

Here's a solution using reduce to iterate over the array of objects, writing a new value to the output whenever we encounter a Page: 1 or at the end of the array:

const arr = [
  { file: '1.pdf', text: 'Page: 1 / 2' },
  { file: '2.pdf', text: 'Page: 2 / 2' },
  { file: '3.pdf', text: 'Page: 1 / 3' },
  { file: '4.pdf', text: 'Page: 2 / 3' },
  { file: '5.pdf', text: 'Page: 3 / 3' },
  { file: '6.pdf', text: 'Page: 1 / 4' },
  { file: '7.pdf', text: 'Page: 2 / 4' },
  { file: '8.pdf', text: 'Page: 3 / 4' },
  { file: '9.pdf', text: 'Page: 4 / 4' },
  { file: '10.pdf', text: 'Page: 1 / 2' },
  { file: '11.pdf', text: 'Page: 2 / 2' },
]

const result = arr.reduce(({ fnum, pages, files }, { file, text }, i, a) => {
  const pgnum = text.match(/Page: (\d )/)[1]
  if (i == a.length - 1) {
    pages.push(file)
    files[`${  fnum}.pdf`] = pages
    return files
  }
  else if (pgnum == 1 && pages.length) {
    files[`${  fnum}.pdf`] = pages
    pages = [file]
  }
  else {
    pages.push(file)
  }
  return { fnum, pages, files }
}, { fnum : 0, pages : [], files : {} });

console.log(result)

  • Related