Sorting an array based on a inner array

Viewed 61

I want to sort an array based on a inner array value sorted alphabetically. example.

i want this array to be sorted by the prefix "old" so old A, old B etc

const array = [
  { personName: "Vans", personTags: ["young",  "old A"] },
  { personName: "Lia", personTags: ["young",  "ok"] },
  { personName: "Rein", personTags: ["old B", "hairless", "ok"] },
  { personName: "Cris", personTags: ["old A",  "old B", "acrounimouslyness"] },
  { personName: "Mercy", personTags: ["young", "hairless", "ok"] },
  { personName: "Cbum", personTags: ["old C", "hairless", "young"] },
];

becomes

const array = [
  { personName: "Vans", personTags: ["young",  "old A"] },
  { personName: "Cris", personTags: ["old A",  "old B", "acrounimouslyness"] },
  { personName: "Rein", personTags: ["old B", "hairless", "ok"] },
  { personName: "Cbum", personTags: ["old C", "hairless", "young"] },
];

//would be removed

{ personName: "Lia", personTags: ["young", "ok"] }, { personName: "Mercy", personTags: ["young", "hairless", "ok"] },

2 Answers
  • Using Array#reduce, iterate over the array while updating an array of elements having an old tag. In each iteration, get the list of old tags using Array#filter and String#startsWith. If the list is not empty, push a new object to the accumulator with a special property sortedOldTags which is basically the current old tags sorted (using Array#sort, String#localeCompare, and Array#join).
  • Using Array#sort, sort the above array using the special property.
  • Using Array#map, return the sorted list taking out the special property from every element.

const array = [
  { personName: "Vans", personTags: ["young",  "old A"] },
  { personName: "Lia", personTags: ["young",  "ok"] },
  { personName: "Rein", personTags: ["old B", "hairless", "ok"] },
  { personName: "Cris", personTags: ["old A",  "old B", "acrounimouslyness"] },
  { personName: "Mercy", personTags: ["young", "hairless", "ok"] },
  { personName: "Cbum", personTags: ["old C", "hairless", "young"] },
];

const arrWithSortProp = array.reduce((arr, e) => {
  const { personTags = [] } = e;
  const oldTags = personTags.filter(tag => tag.startsWith("old"));
  if(oldTags.length) {
    arr.push({ 
      ...e, 
      sortedOldTags: oldTags.sort((a, b) => a.localeCompare(b)).join() 
    });
  }
  return arr;
}, []);

const sorted = arrWithSortProp
  .sort(({ sortedOldTags: a }, { sortedOldTags: b }) => a.localeCompare(b))
  .map(({ sortedOldTags, ...e }) => e);

console.log(sorted);

You could filter then sort:

const array = [
  { personName: "Vans", personTags: ["young", "old A"] },
  { personName: "Lia", personTags: ["young", "ok"] },
  { personName: "Rein", personTags: ["old B", "hairless", "ok"] },
  { personName: "Cris", personTags: ["old B", "old A", "acrounimouslyness"] },
  { personName: "Mercy", personTags: ["young", "hairless", "ok"] },
  { personName: "Cbum", personTags: ["old C", "hairless", "young"] },
];

const getFirstOldElement = arr => {
  return arr
    .filter(s => s.startsWith("old"))
    .sort()
    .at(0);
};

const newArray = array
  .filter(
    obj =>
      (obj.personTags || []).findIndex(s => s.startsWith("old")) !== -1
  )
  .sort((a, b) =>
    getFirstOldElement(a.personTags).localeCompare(getFirstOldElement(b.personTags))
  );

console.log(newArray);

Related