1

Been going around in circles with this for a while.

For example let's say I have different times slots stored as this

let timechunks1 = [["09:00", "10:00", "11:00"], ["09:00", "10:00", "11:00"], ["09:00", "10:00", "11:00", "12:00"]] 
let timechunks2 = [["09:00", "10:00", "11:00"], ["09:00", "10:00", "11:00"], ["09:00", "10:00"]]


 for (let i=0; i< timechunks.length; i++) {
 differences.push(_.difference(timechunks[0], timechunks[i]))      
}

Would need to extract 12:00 since it doesn't appear in others. Closest I got was with underscore _difference but alas it's not doing what I expected.

For timechunks1 I'm looking to return "12:00" For timechunks2 I'm looking for a way to return "11:00"

Added another example

[
["09:00", "10:00", "11:00" ,"13:00"],
["09:00", "10:00", "11:00", "13:00"], 
["09:00", "10:00", "11:00", "12:00"]
]  

for which it would return ["13:00", "12:00"]

0

5 Answers 5

2

In set-theoretic terms, what you are looking for is the symmetric difference. You can find this set by taking the union and subtracting the intersection:

function symmetricDifference(...sets) {
    return _.difference(_.union(...sets), _.intersection(...sets));
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks ! Learned something new :) Seeing the venn diagrams helps visualize it better ) If I knew how it's called would have found that Lodash even has a function that does this called _.xor() but doesn't go all the way lodash.com/docs/4.17.15#xor
What do you mean by "doesn't go all the way"?
1

You can build this on implementations of intersection, difference, and uniq. Here's how I might do it with Ramda's versions:

const notCommon = (xs, common = xs .reduce (intersection)) => 
  uniq (xs .flatMap (x => difference (x, common)))


const timechunks1 = [["09:00", "10:00", "11:00"], ["09:00", "10:00", "11:00"], ["09:00", "10:00", "11:00", "12:00"]] 
const timechunks2 = [["09:00", "10:00", "11:00"], ["09:00", "10:00", "11:00"], ["09:00", "10:00"]]
const timechunks3 = [["09:00", "10:00", "11:00" ,"13:00"], ["09:00", "10:00", "11:00", "13:00"], ["09:00", "10:00", "11:00", "12:00"]]

console .log (notCommon (timechunks1))
console .log (notCommon (timechunks2))
console .log (notCommon (timechunks3))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script>
<script> const {intersection, uniq, difference} = R                  </script>

We find the elements in common to all the sets by using intersection Here we reduce over Ramda's binary version. Other versions might let you do something like common = intersection (xs) or common = intersection (...xs), depending on their exact API. Then we flatMap a difference function over the timechunks, returning the values not found in common. And finally we take only the uniq elements of that list.

3 Comments

Thanks ! Quite powerful data manipulation will look more into ramda! This covers all edge cases. I will implement this right away. In the meanwhile I had looked at the problem the other way around and only return duplicates that appear less times than the timechunks array length which I knew beforehand represents the timeslots for each available agent.
For what it's worth, this is equivalent to my answer.
@Julian: yes it is. Interesting, I've never thought about symmetric difference extending beyond two inputs.
0

Here is an immutable way of doing it

function findTimeSlot(timechunks){
    const slots = _.map(_.zip(...timechunks), _.compact);
    const maxChunk = _.max(_.map(slots, slot => slot.length));

    return _.unique(_.find(slots, (slot) => slot.length < maxChunk));
}

returns

["11:00"] for findTimeSlot(timechunks2)

And

["12:00"] for findTimeSlot(timechunks1)

Let know if it works.

Comments

0
function findUniqueTimeSlots(timechunks) {
  const hm = {};
  timechunks.flat(1).forEach(el => {
    if (hm.hasOwnProperty(el)) {
      hm[el] += 1;
    } else {
      hm[el] = 1;
    }
  });
  return Object.keys(hm).filter(key => hm[key] === 1);
}

Comments

0

You could achieve that by following these steps:

  • find the common timechunk, _.intersection(...timechunks)
  • iterate the timechunks and find the difference of each from the common, _.difference(timechunk, commons)

Below snippet could help you

const timechunks1 = [
  ["09:00", "10:00", "11:00"],
  ["09:00", "10:00", "11:00"],
  ["09:00", "10:00", "11:00", "12:00"],
]
const timechunks2 = [
  ["09:00", "10:00", "11:00"],
  ["09:00", "10:00", "11:00"],
  ["09:00", "10:00"],
]
const timechunks3 = [
  ["09:00", "10:00", "11:00", "13:00"],
  ["09:00", "10:00", "11:00", "13:00"],
  ["09:00", "10:00", "11:00", "12:00"],
]

const getDifferences = (timechunks) =>
  _.chain(timechunks)
    .map((timechunk) => _.difference(timechunk, _.intersection(...timechunks)))
    .flatten()
    .uniq()
    .value()

console.log(getDifferences(timechunks1))
console.log(getDifferences(timechunks2))
console.log(getDifferences(timechunks3))
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

1 Comment

Note that you call intersection repeatedly on the same values.

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.