Complicated issue with arrays

Viewed 85

I have a complicated problem we need to solve.
I have an array which looks like this:

var array = [
             ["1hszZhsez7", 0, "mb12", 0],
             ["87hJKLi893", 1, "tt43", 0],
             ["jchd79dcic", 1, "tt43", 2],
             ["as0w9ejasm", 1, "tt43", 1],
             ["coosihchw9", 0, "zz00", 0],
             ["vs0x0j9ndm", 1, "uu33", 0],
             ["00s0kd20r7", 1, "uu33", 2],
             ["xassdwddao", 1, "uu33", 1],
             ["caosw8ncxc", 2, "uu33", 0]
            ];   

This array always has different values. So let's get in.
The array has basically this values:

var array = [
             [id, type, code, priority]
            ];      

id: The id is unique. Nothing special.
type: There are three different types. 0, 1 and 2.
code: The code is NOT unique. It can be the same for multiple array items.
priority: The priority is a number. If the number is low, the priority is high. If the number is large, priority is low.


The task:
First, we need to sort the different types into different arrays. So that it looks like this:

var type_zero = [
                 ["coosihchw9", 0, "zz00", 0]
                ];   

var type_one = [
                 ["87hJKLi893", 1, "tt43", 0],
                 ["jchd79dcic", 1, "tt43", 2],
                 ["as0w9ejasm", 1, "tt43", 1],
                 ["vs0x0j9ndm", 1, "uu33", 0],
                 ["00s0kd20r7", 1, "uu33", 2],
                 ["xassdwddao", 1, "uu33", 1]
                ];  
 
var type_two = [
                 ["caosw8ncxc", 2, "uu33", 0]
                ];  

That's easy with this function:

 array.forEach(function(item) {
      if (item[1] === 0) {
        type_zero.push([item[0], item[1], item[2], item[3], item[4], item[5]]);
      }
      else if (item[1] === 1) {
        type_one.push([item[0], item[1], item[2], item[3], item[4], item[5]]);
      }
      else if (item[1] === 2) {
        type_two.push([item[0], item[1], item[2], item[3], item[4], item[5]]);
      }
    });     

But then the headache starts. We need to make a separate array for every code group. But we never know how much different codes there are. So we can not make static arrays.
Whatever which code we use. In the end, it should look like this, based on our example array.

var type_zero_zz00 = [
                      ["coosihchw9", 0, "zz00", 0]
                     ];

var type_one_tt43 = [
                      ["87hJKLi893", 1, "tt43", 0],
                      ["jchd79dcic", 1, "tt43", 2],
                      ["as0w9ejasm", 1, "tt43", 1],
                     ];

 var type_one_uu33 = [
                      ["vs0x0j9ndm", 1, "uu33", 0],
                      ["00s0kd20r7", 1, "uu33", 2],
                      ["xassdwddao", 1, "uu33", 1]
                     ];
      
 var type_two_uu33 = [
                      ["caosw8ncxc", 2, "uu33", 0]
                     ];  

Why I need these arrays? In the next step, I have to do a forEach loop for every array list to proceed. I hope someone knows a solution because this problem killed many days and the thoughts at the impossibility are going bigger.
Thanks in advance,
Marius

7 Answers

I see all you need is create functions to obtain the information you need instead of creating lots of different variables.

Below an idea of what you need to be done, not the 100% accurate version of what you need

var array = [
             ["1hszZhsez7", 0, "mb12", 0],
             ["87hJKLi893", 1, "tt43", 0],
             ["jchd79dcic", 1, "tt43", 2],
             ["as0w9ejasm", 1, "tt43", 1],
             ["coosihchw9", 0, "zz00", 0],
             ["vs0x0j9ndm", 1, "uu33", 0],
             ["00s0kd20r7", 1, "uu33", 2],
             ["xassdwddao", 1, "uu33", 1],
             ["caosw8ncxc", 2, "uu33", 0]
            ];   
            
   function getByCode(code){
       return array.filter( item => item[1] === code);
   }
   
   function getByGroup(group){
       return array.filter( item => item[2] === group);
   }

You can use a single array and just use the code as the array index.

var output = [];

var array = [
  ["1hszZhsez7", 0, "mb12", 0],
  ["87hJKLi893", 1, "tt43", 0],
  ["jchd79dcic", 1, "tt43", 2],
  ["as0w9ejasm", 1, "tt43", 1],
  ["coosihchw9", 0, "zz00", 0],
  ["vs0x0j9ndm", 1, "uu33", 0],
  ["00s0kd20r7", 1, "uu33", 2],
  ["xassdwddao", 1, "uu33", 1],
  ["caosw8ncxc", 2, "uu33", 0]
];

array.forEach(function(item) {
  if (output[item[1]] == undefined) {
    output[item[1]] = []
  }
  output[item[1]].push(item);
});

console.log(0, output[0])
console.log(1, output[1])
console.log(2, output[2])

What about using a two-dimensional dict ? By doing so you would end up with a data structure like this where you can add new values (which are dicts themselves) for type and code group:

var type = {};
type["0"]["zz00"] = [
                  ["coosihchw9", 0, "zz00", 0]
                 ];
type["1"]["tt43"] = [
                  ["87hJKLi893", 1, "tt43", 0],
                  ["jchd79dcic", 1, "tt43", 2],
                  ["as0w9ejasm", 1, "tt43", 1],
                 ];

type["1"]["uu33"] = [
                  ["vs0x0j9ndm", 1, "uu33", 0],
                  ["00s0kd20r7", 1, "uu33", 2],
                  ["xassdwddao", 1, "uu33", 1]
                 ];
  
type["2"]["uu33"] = [
                  ["caosw8ncxc", 2, "uu33", 0]
                 ];  

Create a map that handles the dynamic code :

function groupArray(arr) {
  const map = {};
  arr.forEach(element => {
    const [id, type, code, priority] = element;
    map[code] = Array.isArray(map[code]) ? [...map[code], element] : [element];
  });
  return map;
}

const type_zero_group = groupArray(type_zero)
const type_one_group = groupArray(type_one)
const type_two_group = groupArray(type_two)

Now if the types themselves are getting dynamic, create a mapper for them too. Two-level maps.

Instead of creating a new variable for each combination of type & code, create an object with a property for each combination. Now, it's actually a simple grouping by two keys problem. You can use Array.reduce(), and a generate an object or a Map:

const array = [["1hszZhsez7",0,"mb12",0],["87hJKLi893",1,"tt43",0],["jchd79dcic",1,"tt43",2],["as0w9ejasm",1,"tt43",1],["coosihchw9",0,"zz00",0],["vs0x0j9ndm",1,"uu33",0],["00s0kd20r7",1,"uu33",2],["xassdwddao",1,"uu33",1],["caosw8ncxc",2,"uu33",0]];

const types = ['zero', 'one', 'two'];

const result = array.reduce((r, row) => {
  const [, type, code] = row;

  const key = `type_${types[type]}_${code}`;
  
  if(!r[key]) r[key] = [];
  
  r[key].push(row);

  return r;
}, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You build an object like this to solve your problems, instead of trying to make many variables.

const results = {
  0: {},
  1: {},
  2: {},
};

for (let item of array) {
  let [id, type, code, priority] = item;

  if (results[type][code] === undefined) {
    results[type][code] = [item];
  } else {
    results[type][code] = results[type][code].concat([item]);
  }
}

You could then map through these objects like this:

for (let type of Object.keys(results)) {
  for (let code of Object.keys(results[type])) {
    const array = results[type][code];
  }
}

You can do this with reduce method and object as accumulator that you can use to group values by type-code as keys.

var array = [
  ["1hszZhsez7", 0, "mb12", 0],
  ["87hJKLi893", 1, "tt43", 0],
  ["jchd79dcic", 1, "tt43", 2],
  ["as0w9ejasm", 1, "tt43", 1],
  ["coosihchw9", 0, "zz00", 0],
  ["vs0x0j9ndm", 1, "uu33", 0],
  ["00s0kd20r7", 1, "uu33", 2],
  ["xassdwddao", 1, "uu33", 1],
  ["caosw8ncxc", 2, "uu33", 0]
];

const result = array.reduce((r, e) => {
  const [id, type, code, priority] = e;
  const key = `${type}|${code}`;

  if (!r[key]) {
    r[key] = []
  }

  r[key].push(e);
  return r;
}, {})

console.log(Object.values(result))

Related