Reputation: 8868
var myObject = {
word1: {
a: ['1.json', '2.json']
b: ['3.json', '4.json', '5.json']
},
word2: {
x: ['1.json', '3.json'],
y: ['2.json', '4.json'],
z: ['5.json']
}
}
So the output of this script should be:
['1.json', '4.json', '5.json']
Here is the logic, I want to be able to get the files that use the min stuff. Take for example "1.json", that one shows in:
myObject.word1.a
but also on
myObejct.word2.x
This means that '1.json' is no longer going to be used. But will be added to the output.
output so far: [1.json]
Here comes the tricky part.
Now lets go to '2.json'. It can't be used since 'myObject.word1.a' is already in use by '1.json', so just skip it.
output so far: [1.json]
Now lets go to '3.json', it appears on myobject.word1.b it apperas on myObject.word2.x // BUT 1.json already filled this position
So it can't be used
output so far: [1.json]
Lets go to 4.json it appears on myobject.word1.b it appears on myobject.word2.y <- here remember we skipped '2.json' since it did not work. So '4.json' is accepted
output so far: [1.json, 4.json]
lets go to 5.json it appears on myobject.word1.b it also appears on myobject.word2.z
this can be used since the "z" key has not been used by any other file.
Upvotes: 1
Views: 52
Reputation: 28404
Let's name the combination of the word
and letter
as "dir", and the array elements as "files".
While Iterating over each dir you can save them in a Set
(dirs).
In each dir, you can loop over its files and update a Map
(fileDirsMap) saving this file's dirs.
After this step, you would have a set
of dirs available, and a map
of each file and its dirs:
dirs: [ "word1.a", "word1.b", "word2.x", "word2.y", "word2.z" ]
fileDirsMap: [
[ "1.json", [ "word1.a", "word2.x" ] ],
[ "2.json", [ "word1.a", "word2.y" ] ],
[ "3.json", [ "word1.b", "word2.x" ] ],
[ "4.json", [ "word1.b", "word2.y" ] ],
[ "5.json", [ "word1.b", "word2.z" ] ]
]
Now, you can iterate over fileDirsMap
's entries
(Array#reduce
is suitable here). In each iteration, check if this file has all its dirs "not taken", if they are, add the file to the resulting array (acc
) and remove all its dirs from the set (dirs
) (setting them as taken).
const myObject = {
word1: {
a: ['1.json', '2.json'],
b: ['3.json', '4.json', '5.json']
},
word2: {
x: ['1.json', '3.json'],
y: ['2.json', '4.json'],
z: ['5.json']
}
};
const fileDirsMap = new Map();
const dirs = new Set();
Object.entries(myObject).forEach(([word, letters]) => {
Object.entries(letters).forEach(([letter, files]) => {
const dir = `${word}.${letter}`;
dirs.add(dir);
files.forEach(file =>
fileDirsMap.set(file, [...(fileDirsMap.get(file) || []), dir])
);
});
});
const res = [...fileDirsMap.entries()].reduce((acc,[file, fileDirs]) => {
const allDirsNotTaken = fileDirs.every(fileDir => dirs.has(fileDir));
if(allDirsNotTaken) {
acc.push(file);
fileDirs.forEach(fileDir => dirs.delete(fileDir));
}
return acc;
}, []);
console.log(res);
Upvotes: 1