JSFiddle - React, Tailwind, and code Playground

by Stepan Parunashvili

JavaScript

function parseCSV(csvStr) {
  return csvStr
    .trim()
    .split("\n")
    .reduce((res, rowStr) => {
      const [name, cityStr] = rowStr.split(":");
      return res.set(name.trim(), new Set(cityStr.split(",")));
    }, new Map());
}

function intersect(setA, setB) {
  return new Set([...setA].filter(x => setB.has(x)));
}

function difference(setA, setB) {
  return new Set([...setA].filter(x => !setB.has(x)));
}

function nameToInfo(myName, nameToCities) {
  const myCities = nameToCities.get(myName);
  const nameToInfo = [...nameToCities.entries()]
    .filter(([name, cities]) => name !== myName)
    .map(([name, cities]) => [name, cities, intersect(myCities, cities)]);

  const myCount = myCities.size;
  return nameToInfo
    .filter(([name, cities, intersection]) => {
      return intersection.size / myCount >= 0.5;
    })
    .sort(
      (
        [_nameA, _citiesA, intersectionA],
        [_nameB, _citiesB, intersectionB]
      ) => {
        return intersectionB.size - intersectionA.size;
      }
    );
}

function bestTravelBuddies(myName, nameToCities) {
  return nameToInfo(myName, nameToCities).map(
    ([name, _cities, _intersection]) => name
  );
}

function bestRecommendations(myName, nameToCities) {
  return nameToInfo(myName, nameToCities)
    .map(([name, cities, intersection]) => {
      return difference(cities, intersection);
    })
    .reduce((res, xs) => {
      xs.forEach(x => res.add(x));
      return res;
    }, new Set());
}

const NAME = "Stepan";

const strOne = `
  Jack:BJ,SEA,
  Joe:LA,MTA,
`;

// const firstOne = parseCSV(strOne);
// console.log("we parsed correctly", firstOne);

const strWithOneMatch = `
  Jack:BJ,SEA,SF
  Jane:BJ,SEA,MTA,SF,LA
  Joe:LA,MTA,SF,NYC,SF
  Stepan:BJ,SEA,MTA
`;

const shouldBeOneMatch = parseCSV(strWithOneMatch);
console.log(
  "expecting [Jane, Jack]",
  bestTravelBuddies(NAME, shouldBeOneMatch)
);

console.log(
  "expecting [[SF, LA], [SF]]",
  bestRecommendations(NAME, shouldBeOneMatch)
);