ahkam
ahkam

Reputation: 767

How to remove duplicate sub object array from JS array?

I have a js object array as below

[
[
 {file: 'file1',
  status: 'pending',
  time: '2021-08-13 11:20:00'
 },
 {file: 'file2',
  status: 'pending',
  time: '2021-08-13 11:20:00'
 }
],
[
 {file: 'file1',
  status: 'completed',
  time: '2021-08-13 09:30:00'
 },
 {file: 'file2',
  status: 'completed',
  time: '2021-08-13 09:30:00'
 }
],
[
 {file: 'file3',
  status: 'completed',
  time: '2021-08-14 06:50:00'
 }
]
]

And i need to filter the array based on the file field and remove the duplicated sub arrays. So the output should look like

[
[
 {file: 'file1',
  status: 'pending',
  time: '2021-08-13 11:20:00'
 },
 {file: 'file2',
  status: 'pending',
  time: '2021-08-13 11:20:00'
 }
],
[
 {file: 'file3',
  status: 'completed',
  time: '2021-08-14 06:50:00'
 }
]
]

What is the easiest way to do this. Can we use ES6 here?

Upvotes: 0

Views: 159

Answers (2)

Nitheesh
Nitheesh

Reputation: 19986

Try using Array.reduce.

Please see the code comments for logic.

const input = [
    [
        { file: 'file1', status: 'pending', time: '2021-08-13 11:20:00' },
        { file: 'file2', status: 'pending', time: '2021-08-13 11:20:00' }
    ],
    [
        { file: 'file1', status: 'completed', time: '2021-08-13 09:30:00' },
        { file: 'file2', status: 'completed', time: '2021-08-13 09:30:00' }
    ],
    [
        { file: 'file3', status: 'completed', time: '2021-08-14 06:50:00' }
    ]
]
const output = input.reduce((acc, curr) => {
    let isNodeExist = false;
    /*
     * Each node of the accumulator acc will be an array
     * Which means the accumulator acc is an array of arrays
     * The current node curr will also be an array
     * So we have to verify the array curr has the same set present
     * For that there should be a child node present in acc with the same length of curr
     * Also the each name of curr should be there in that matching node
     */
    acc.forEach((node) => {
        isNodeExist = node.length === curr.length;
        if (isNodeExist) {
            curr.forEach((currNode) => {
                isNodeExist = isNodeExist && (node.find((item) => item.file === currNode.file) !== undefined);
            })
        }
    });
    if(!isNodeExist) {
        acc.push(curr);
    }
    return acc;
}, []);
console.log(output);

Upvotes: 2

vsemozhebuty
vsemozhebuty

Reputation: 13782

If you need to save just the first instance with the same group of names, this is a possible way:

const data = [
  [
    {file: 'file1',
      status: 'pending',
      time: '2021-08-13 11:20:00'
    },
    {file: 'file2',
      status: 'pending',
      time: '2021-08-13 11:20:00'
    }
  ],
  [
    {file: 'file1',
      status: 'completed',
      time: '2021-08-13 09:30:00'
    },
    {file: 'file2',
      status: 'completed',
      time: '2021-08-13 09:30:00'
    }
  ],
  [
    {file: 'file3',
      status: 'completed',
      time: '2021-08-14 06:50:00'
    }
  ],
  [
    {file: 'file2',
      status: 'completed',
      time: '2021-08-14 06:50:00'
    }
  ],
];

const filteredData = [];
const seenFiles = new Set();

for (const group of data) {
  const fileNames = JSON.stringify(group.map(({ file }) => file).sort());

  if (!seenFiles.has(fileNames)) {
    seenFiles.add(fileNames);
    filteredData.push(group);
  }
}

console.log(filteredData);

Upvotes: 1

Related Questions