Sort aray of objects by another array of objects reference

Viewed 274

I need some help to sort this data out, i have an array of products and i need to sort and display by settings configuration. The output must have the same order as settings array (index) and if display is true. Thanks in advance. This is what i tryed:

var products = [
    {id: 0, name: 'Chocolate', category: 'Sweet'},
    {id: 1, name: 'Almendras', category: 'Fruit'},
    {id: 2, name: 'Nueces', category: 'Fruit'},
    {id: 3, name: 'Mermelada', category: 'Jam'},
    {id: 4, name: 'Alfajor', category: 'Sweet'},
    {id: 5, name: 'Queso', category: 'UwU'},
    {id: 6, name: 'Arandanos', category: 'Fruit'},
    {id: 7, name: 'Maracuya', category: 'Fruit'}
];

let settings = [
    {
        name: 'Fruit',
        display: true
    },
    {
        name: 'Jam',
        display: false
    },
    {
        name: 'Sweet',
        display: true
    },
    {
        name: 'UwU',
        display: true
    }
]


let group = products.reduce((r, a) => {
      r[a.category] = [...r[a.category] || [], a];
      return r;
    }, {});

let arrangedProducts = Object.keys(group); 

console.log(group);
console.log(arrangedProducts);

This is my expected output:

/*
expected result = [
    [
        {id: 1, name: 'Almendras', category: 'Fruit'}, 
        {id: 2, name: 'Nueces', category: 'Fruit'}, 
        {id: 6, name: 'Arandanos', category: 'Fruit'},
        {id: 7, name: 'Maracuya', category: 'Fruit'}
    ],
    [
        {id: 0, name: 'Chocolate', category: 'Sweet'},
        {id: 4, name: 'Alfajor', category: 'Sweet'}
    ],
    [
        {id: 5, name: 'Queso', category: 'UwU'}
    ]
]
*/

3 Answers

Solution

  1. Making of groups
  2. Apply settings and retrieve the result

const products = [
  { id: 0, name: "Chocolate", category: "Sweet" },
  { id: 1, name: "Almendras", category: "Fruit" },
  { id: 2, name: "Nueces", category: "Fruit" },
  { id: 3, name: "Mermelada", category: "Jam" },
  { id: 4, name: "Alfajor", category: "Sweet" },
  { id: 5, name: "Queso", category: "UwU" },
  { id: 6, name: "Arandanos", category: "Fruit" },
  { id: 7, name: "Maracuya", category: "Fruit" },
];

const productsGroup = products.reduce((r, a) => {
  r[a.category] = [...(r[a.category] || []), a];
  return r;
}, {});

function applySettings(settings) {
  return settings.filter((s) => s.display).map((s) => productsGroup[s.name]);
}

console.log(
  applySettings([
    {
      name: "Fruit",
      display: true,
    },
    {
      name: "Jam",
      display: false,
    },
  ])
);

console.log(
  applySettings([
    {
      name: "Fruit",
      display: true,
    },
    {
      name: "Sweet",
      display: true,
    },
    {
      name: "UwU",
      display: true,
    },
  ])
);

You can filter your settings list based on the display property and then use Array.map to return a list of objects in products that match the category:

const products = [
    {id: 0, name: 'Chocolate', category: 'Sweet'},
    {id: 1, name: 'Almendras', category: 'Fruit'},
    {id: 2, name: 'Nueces', category: 'Fruit'},
    {id: 3, name: 'Mermelada', category: 'Jam'},
    {id: 4, name: 'Alfajor', category: 'Sweet'},
    {id: 5, name: 'Queso', category: 'UwU'},
    {id: 6, name: 'Arandanos', category: 'Fruit'},
    {id: 7, name: 'Maracuya', category: 'Fruit'}
];

const settings = [
    { name: 'Fruit', display: true },
    { name: 'Jam', display: false },
    { name: 'Sweet', display: true },
    { name: 'UwU', display: true }
];

const result = settings
  .filter(c => c.display)
  .map(c => products.filter(o => o.category == c.name));

console.log(result);

Note that this code does filter the products array for each settings value that has display:true, so may be slow for large arrays. However filter is pretty low overhead and testing with OP's sample data shows this to run 3x the speed of the reduce version; and with a larger products array (99 entries) to run 10x faster.

This should be pretty quick, because it continues on to the next iteration without executing the inner loop when display is false:

var products = [
    {id: 0, name: 'Chocolate', category: 'Sweet'},
    {id: 1, name: 'Almendras', category: 'Fruit'},
    {id: 2, name: 'Nueces', category: 'Fruit'},
    {id: 3, name: 'Mermelada', category: 'Jam'},
    {id: 4, name: 'Alfajor', category: 'Sweet'},
    {id: 5, name: 'Queso', category: 'UwU'},
    {id: 6, name: 'Arandanos', category: 'Fruit'},
    {id: 7, name: 'Maracuya', category: 'Fruit'}
];

let settings = [
    {
        name: 'Fruit',
        display: true
    },
    {
        name: 'Jam',
        display: false
    },
    {
        name: 'Sweet',
        display: true
    },
    {
        name: 'UwU',
        display: true
    }
];
function sortProducts(){
  const r = [];
  let i = -1;
  for(let s of settings){
    if(!s.display){
      continue;
    }
    i++;
    for(let o of products){
      if(s.name === o.category){
        if(r[i]){
          r[i].push(o);
        }
        else{
          r.push([o]);
        }
      }
    }
  }
  return r;
}
console.log(sortProducts());

Related