Script to group elements where every character is same to each other

Viewed 47

For input:

["abc","def","okg","fed","bca"]

expected output should be:

["abc","bca"],["def","fed"],["okg"]

here "abc", "bca" and "def", "fed" contains same character and "okg" there is no element which contains these character

const arr = ["abc", "def", "okg", "fed", "bca"];
let find = (arr) => {
  let res = [];
  for (let i = 0; i < arr.length; i++) {
    for (let j = 1; j < arr.length; j++) {
      if (arr[i].search(arr[j])) {
        res.push(arr[j]);
      }
    }

  }
  return res;
}

console.log(find(arr))

4 Answers

A reduce will do the trick - it seems the shortest code here (apart from the one using lodash)

const arr = ["abc", "def", "okg", "fed", "bca"],
  res = Object.values(arr.reduce((acc, ele) => {
    const key = ele.split("").sort();
    (acc[key] = acc[key] || []).push(ele)
    return acc
  }, {}))
console.log(res)

  • .search returns a number indicating the index of where the match was found. Check that the result isn't -1 instead of checking that the result is truthy. But...

  • .search isn't the right tool here anyway, because it won't find different combinations of the same character. You need a different approach. One way would be to create an object whose keys are the characters found, and the values are the number of occurrences, then use a sorted representation of that object as a key. For example, have both abc and bca turn into something like:

    a,1-b,1-c,1
    

    Iterate through the input array, generating a key for each string, and putting the string on an object with that key. At the end, take the object's values.

const strToKey = (str) => {
  const grouped = {};
  for (const char of str) {
    grouped[char] = (grouped[char] || 0) + 1;
  }
  return Object.entries(grouped)
    .sort((a, b) => a[0].localeCompare(b[0]))
    .join('-');
};

let find = (arr) => {
  const grouped = {};
  for (const str of arr) {
    const key = strToKey(str);
    grouped[key] ??= [];
    grouped[key].push(str);
  }
  return Object.values(grouped);
}
console.log(find(["abc", "def", "okg", "fed", "bca"]));

Another option, when creating the keys, instead of sorting the object afterwards, you could sort the string first:

const strToKey = (str) => {
  const grouped = {};
  for (const char of [...str].sort()) {
    grouped[char] = (grouped[char] || 0) + 1;
  }
  return Object.entries(grouped).join('-');
};

let find = (arr) => {
  const grouped = {};
  for (const str of arr) {
    const key = strToKey(str);
    grouped[key] ??= [];
    grouped[key].push(str);
  }
  return Object.values(grouped);
}
console.log(find(["abc", "def", "okg", "fed", "bca"]));

Using Object.values and groupBy (from lodash), you can get a straightforward solution:

You group your array elements by their "sorted" form and then use Object.values to get the output array.

const arr = ["abc", "def", "okg", "fed", "bca"];

const sortString = (str) => str.split("").sort().join("")
const result = Object.values(_.groupBy(arr, sortString));

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

const input = ["abc","def","okg","fed","bca"]


function getSortedString (str) {
  return [...str].sort().join('');
};

function groupBy(input) {
  const grouped = [];
  while(input.length) {
    const nextInput = [];
    const first = input[0];
    const matched = [first];

    for (let i = 1; i < input.length; i++) {
      if(getSortedString(first) === getSortedString(input[i])) {
        matched.push(input[i])
      } else {
        nextInput.push(input[i])
      }
    } 
   input = nextInput;
   grouped.push(matched);
  }
  console.log(grouped);
}

groupBy(input);

Related