1
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.

9
  • and your code? you tried? Commented Mar 18, 2021 at 22:24
  • 1
    Can you share what you've tried so far? StackOverflow isn't a free code-writing service, and expects you to try to solve your own problem first. Please update your question to show what you have already tried, showing the specific problem you are facing in a minimal, complete, and verifiable example. For further information, please see how to ask good questions, and take the tour of the site. Commented Mar 18, 2021 at 22:26
  • As a hint to get you started, it sounds like you will need two variables (map or set) to keep track of which keys and values have already been seen / assigned as well as one for output. Check these as you iterate through the possibilites and mark slots as used as you go Commented Mar 18, 2021 at 22:29
  • 1
    I don't understand why 5.json can be used given that word1.b is used by 4.json Commented Mar 18, 2021 at 22:35
  • 1
    Yes these constraints are confusing because you change from stepping through keys in a word to stepping through jsons between words to the words themselves in a way that makes it hard to tell what the actual rules of this exercise are. Commented Mar 18, 2021 at 22:44

1 Answer 1

1

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);

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.