0

This is a similar question as this one: Complete missing sequence in array with zeros in javascript

However, I can't seem to go around this problem. This is my array:

const array = [
  [5, 'a', 2.3],
  [6, 'a', 1.7],
  [7, 'a', 5.4],
  [8, 'a', 2.8],
  [9, 'a', 8.5],
  [10, 'a', 9.2],
  [2, 'b', 1.6],
  [5, 'b', 5.7],
  [6, 'b', 8.9],
  [7, 'b', 3.5],
  [8, 'b', 6.1],
  [9, 'b', 1.8],
  [10, 'b', 7.4],
];

console.log(array);

First element: this is my reference value, it ranges from 1 to 10.

Second element: this is a category value.

Third element: this is a value that belongs to the second element, which happened at a timestamp that belongs to the first element.


My issue: I need to make sure that all the unique categories in the second element of the array (e.g., a and b) have the following sequence in the first element: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. If they do not have one of these numbers, then I need to create it, and then assign null to the third element.

Therefore, this is my expected output:

[
  [1, 'a', null],
  [2, 'a', null],
  [3, 'a', null],
  [4, 'a', null],
  [5, 'a', 2.3],
  [6, 'a', 1.7],
  [7, 'a', 5.4],
  [8, 'a', 2.8],
  [9, 'a', 8.5],
  [10, 'a', 9.2],
  [1, 'b', null],
  [2, 'b', 1.6],
  [3, 'b', null],
  [4, 'b', null],
  [5, 'b', 5.7],
  [6, 'b', 8.9],
  [7, 'b', 3.5],
  [8, 'b', 6.1],
  [9, 'b', 1.8],
  [10, 'b', 7.4],
];

Any ideas?

2 Answers 2

2

You can create a range from 1 to 10, loop over it and when you can't find an association in your array, create a new element and push it. Do that for every category and you're good.

const range = new Array(0).fill().map((_, i) => i + 1); // from 1 to 10

const categories = array
                     .map(x => x[1]) // get categories
                     .filter((val, i, self) => self.indexOf(val) === i) // uniq

categories.forEach(categ => {
  range.forEach(n => {
    const alreadyInArray = array.some(x => x[0] === n && x[1] === categ);
    
    if (!alreadyInArray) {
      const newEntry = [n, categ, null];

      array.push(newEntry);
    }
  });
})

You can of course replace the forEach with classic for loops

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I have learnt to get unique elements with filter. I had the logic, but didn't know that I could use the filter's 3rd argument xD
This requires looping over all elements in the array for every one of the elements that need to be present. It works, but is inefficient for large amounts of data. In this case, an indexed data structure should be used (an implementation of a HashMap for example).
1

A functional solution, first get the categories, then for each category fill the corresponding array.

const array = [
  [5, 'a', 2.3],
  [6, 'a', 1.7],
  [7, 'a', 5.4],
  [8, 'a', 2.8],
  [9, 'a', 8.5],
  [10, 'a', 9.2],
  [2, 'b', 1.6],
  [5, 'b', 5.7],
  [6, 'b', 8.9],
  [7, 'b', 3.5],
  [8, 'b', 6.1],
  [9, 'b', 1.8],
  [10, 'b', 7.4],
];

const getMissingIndicesFromCategory = (tuples) => {
  const indices = tuples.map(tuple => tuple[0])
  const fullIndices = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  return fullIndices.filter(index => !indices.includes(index));
}

const createMissingTuples = (missingIndices, category) => {
  return missingIndices.map(index => [index, category, null])
}


const completeCategoryTuples = (array, category) => {
  const categoryTuples = array.filter(tuple => tuple[1] === category)
  const missingIndices = getMissingIndicesFromCategory(categoryTuples)
  const missingTuples = createMissingTuples(missingIndices, category)
  return [...categoryTuples, ...missingTuples].sort((tuple1, tuple2) => tuple1[0] > tuple2[0] ? 1 : -1)
}

const getAllUniqueCategories = (array) => Array.from(new Set(array.map(tuple => tuple[1])))

const fillArray = (array) => {
  const categories = getAllUniqueCategories(array)
  return categories.flatMap(category => completeCategoryTuples(array, category))
}


const fullArray = fillArray(array)
console.log(fullArray)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.