I am passing an object with 5 arrays to my function. One of the properties is called ‘Indexes’. What this function is doing is filling in the array with zeros in ascending order, all other arrays follow the Indexes array as their index so if the Indexes array is [1,3] it will fill it with [1,2,3] and all arrays will have 0 in position 2.
My problem is when Indexes contain .5 (work-related, so I have to roll with it), if I have [43, 44.5, 45] I want to get [43, 44, 44.5, 45]. But the way I wrote my code seems to skip with whole numbers completely, and I think I am making it more complicated for myself than it needs to be.
Here’s the function
function fillMissingValues(csv) {
const indexes = csv.Indexes;
const allReads = csv['All reads'];
const trimmedByAdapterOrQuality = csv['Trimmed by Adapter or Quality'];
const trimmedByAdapter = csv['Trimmed by adapter'];
const trimmedByQuality = csv['Trimmed by quality'];
const filledIndexes = [];
const filledAllReads = [];
const filledTrimmedByAdapterOrQuality = [];
const filledTrimmedByAdapter = [];
const filledTrimmedByQuality = [];
let lastIndex = 0;
for (let i = 0; i < indexes.length; i++) {
const index = indexes[i];
const value = allReads[i];
const taq = trimmedByAdapterOrQuality[i];
const ta = trimmedByAdapter[i];
const tq = trimmedByQuality[i];
while (lastIndex < index) {
filledIndexes.push(lastIndex);
filledAllReads.push(0);
filledTrimmedByAdapterOrQuality.push(0);
filledTrimmedByAdapter.push(0);
filledTrimmedByQuality.push(0);
lastIndex++;
}
filledIndexes.push(index);
filledAllReads.push(value);
filledTrimmedByAdapterOrQuality.push(taq);
filledTrimmedByAdapter.push(ta);
filledTrimmedByQuality.push(tq);
lastIndex++;
}
// Fill the remaining indexes with zeros
const maxIndex = Math.max(...indexes);
while (lastIndex <= maxIndex) {
filledIndexes.push(lastIndex);
filledAllReads.push(0);
filledTrimmedByAdapterOrQuality.push(0);
filledTrimmedByAdapter.push(0);
filledTrimmedByQuality.push(0);
lastIndex++;
}
const filledCSV = {
Indexes: filledIndexes,
'All reads': filledAllReads,
'Trimmed by Adapter or Quality': filledTrimmedByAdapterOrQuality,
'Trimmed by adapter': filledTrimmedByAdapter,
'Trimmed by quality': filledTrimmedByQuality
};
return filledCSV;
}
Example of passing data,
csv = {
Indexes:[ 3, 4, 6.5, 8]
'All reads': [1, 2, 3, 4],
'Trimmed by Adapter or Quality': [1, 2, 3, 4],
'Trimmed by adapter': [1, 2, 3, 4],
'Trimmed by quality': [1, 2, 3, 4],
}
so output should be
filledCSV = {
Indexes:[0, 1, 2, 3, 4, 5, 6, 6.5, 7, 8]
'All reads': [0, 0, 0, 1, 2, 0, 0, 3, 0, 4],
'Trimmed by Adapter or Quality': [0, 0, 0, 1, 2, 0, 0, 3, 0, 4],
'Trimmed by adapter': [0, 0, 0, 1, 2, 0, 0, 3, 0, 4],
'Trimmed by quality': [0, 0, 0, 1, 2, 0, 0, 3, 0, 4],
}
2
Answers
Create an array with all the integers from 0 to
Math.max(...indexes)
.Merge
indexes
into this array, remove duplicates, and sort it.Loop over this combined array. If the element is in
indexes
, push the corresponding elements of all the other properties into the corresponding property infilledCSV
. If not, push0
.Indexes
with an incremented value from0
and fill all the arrays accordinglyFor a more performant version pre-allocate the arrays: