array.reduce and null values - javascript

I am developing a javascript-based application, therein I have an array as below:
[-12.66, 268.2, 48.99, -1264.5, 20550, 91.2, 0, 0, 0, 0, 0, 0, 0, 0, 9235.5, 1500, 0, 0, 18.99, 0, 0, null, null, null, null, null, null, null, null, null, null]
now I want to do cumulative summation of below error until it returns null value, once it has started reading null value it should return null from there or should return as it is and should not do cumulative summation from there.
I have done as below using array.reduce:
let resultArray=[];
array1.reduce(function (acc, curr, index) { return resuleArray[index] = acc + curr }, 0);
// here array1 is source array.
However, this returns as below
[-12.66, 255.54, 304.53, -959.97, 19590.03, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 28916.73, 30416.73, 30416.73, 30416.73, 30435.72, 30435.72, 30435.72, 30435.72, 30435.72, 30435.72, 30435.72, 30435.72, 30435.72, 30435.72, 30435.72, 30435.72, 30435.72];
What I would like to have is like below :
[-12.66, 255.54, 304.53, -959.97, 19590.03, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 19681.23, 28916.73, 30416.73, 30416.73, 30416.73, 30435.72, 30435.72, null, null, null, null, null, null, null, null, null, null, null];
Please note that I will always have trailing values as null.

So, check if curr is null.
const array1 = [-12.66, 268.2, 48.99, -1264.5, 20550, 91.2, 0, 0, 0, 0, 0, 0, 0, 0, 9235.5, 1500, 0, 0, 18.99, 0, 0, null, null, null, null, null, null, null, null, null, null];
let resultArray = [];
array1.reduce(function(acc, curr, index) {
const sum = acc + curr;
if (curr === null) {
resultArray[index] = null;
} else {
resultArray[index] = sum
}
return sum;
}, 0);
console.log(resultArray);
This way even if you put a number after some null values it will continue with the cumulative summation

You need just to modify a little bit your code like this:
array1.reduce(function (acc, curr, index) {
return resultArray[index] = curr !== null ? acc + curr : null
}, 0);

Insert null in rest of the index once null is interpreted
const array1 = [-12.66, 268.2, 48.99, -1264.5, 20550, 91.2, 0, 0, 0, 0, 0, 0, 0, 0, 9235.5, 1500, 0, 0, 18.99, 0, 0, null, null, null, null, null, null, null, null, null, null];
let resultArray = [];
let isNullInterpreted = false;
const output = array1.reduce(function (acc, curr, index) {
isNullInterpreted = isNullInterpreted || curr == null;
return resultArray[index] = isNullInterpreted ? null : acc + curr;
}, 0);
console.log(resultArray);
console.log(output);
Stop iterating the loop once null is interpreted
const array1 = [-12.66, 268.2, 48.99, -1264.5, 20550, 91.2, 0, 0, 0, 0, 0, 0, 0, 0, 9235.5, 1500, 0, 0, 18.99, 0, 0, null, null, null, null, null, null, null, null, null, null];
let resultArray = [];
let isNullInterpreted = false;
const output = array1.reduce(function (acc, curr, index) {
isNullInterpreted = isNullInterpreted || curr == null;
if (!isNullInterpreted) {
resultArray[index] = acc + curr;
}
return resultArray[resultArray.length - 1]
}, 0);
console.log(resultArray);
console.log(output);

You could take a closure over the sum and add unil the value is null.
const
data = [-12.66, 268.2, 48.99, -1264.5, 20550, 91.2, 0, 0, 0, 0, 0, 0, 0, 0, 9235.5, 1500, 0, 0, 18.99, 0, 0, null, null, null, null, null, null, null, null, null, null],
result = data.map((sum => v => sum === null || v === null
? sum = null
: sum += v
)(0));
console.log(...result);

Related

Merge Array by one of its value

I want to filter from two different arrays based on following array named = timeArray
["13:37", "13:36", "13:35", "13:34", "13:33", "13:32"]
first array looks like this .. array1
[
[23323.25,23323.65,23313.25,23315.05,97,62,"13:36"],
[23315.05,23315.2,23314,23315,8,9,"13:37"]
]
second array looks like this .. array2
[
[23310,23310,23300,23300,0,0,"13:34"],
[23309.75,23343.1,23305,23323.25,0,0,"13:35"],
[23296.5,23310,23294.65,23309.8,0,0,"13:30"],
[23308.35,23310,23301,23306.15,0,0,"13:31"],
[23308,23309,23292.5,23299.55,0,0,"13:32"],
[23299.55,23310,23294.15,23310,0,0,"13:33"],
[23310,23310,23300,23300,0,0,"13:34"],
[23309.75,23343.1,23305,23324.65,0,0,"13:35"],
[23308,23309,23292.5,23299.55,0,0,"13:36"]
]
Based on Timearray elements, First should check array1 and then array 2 6th element and expected result should look like
[
[23308,23309,23292.5,23299.55,0,0,"13:32"],
[23299.55,23310,23294.15,23310,0,0,"13:33"],
[23310,23310,23300,23300,0,0,"13:34"],
[23309.75,23343.1,23305,23324.65,0,0,"13:35"],
[23323.25,23323.65,23313.25,23315.05,97,62,"13:36"],
[23315.05,23315.2,23314,23315,8,9,"13:37"]
]
I tried something like below
var finalarray = [];
for(var key in timeArray)
{
var timer = timeArray[key];
for(var key in array1)
{
arraytime1 = array1[key][6];
if(timer == arraytime1)
{
finalarray.push(arraytime1);
}
}
for(var key in array2)
{
arraytime2 = array2[key][6];
if(timer == arraytime2)
{
finalarray.push(arraytime2);
}
}
}
But "13:36" is added two times...Also if the element based on timerArray is not present it should be null... also is there any better way to do it ? I feel like it takes much resource to process... Thank you.
You could take an object for keeping the fist array for each time and map the result.
const
timeArray = ["13:37", "13:36", "13:35", "13:34", "13:33", "13:32"],
array1 = [[23323.25, 23323.65, 23313.25, 23315.05, 97, 62, "13:36"], [23315.05, 23315.2, 23314, 23315, 8, 9, "13:37"]],
array2 = [[23310, 23310, 23300, 23300, 0, 0, "13:34"], [23309.75, 23343.1, 23305, 23323.25, 0, 0, "13:35"], [23296.5, 23310, 23294.65, 23309.8, 0, 0, "13:30"], [23308.35, 23310, 23301, 23306.15, 0, 0, "13:31"], [23308, 23309, 23292.5, 23299.55, 0, 0, "13:32"], [23299.55, 23310, 23294.15, 23310, 0, 0, "13:33"], [23310, 23310, 23300, 23300, 0, 0, "13:34"], [23309.75, 23343.1, 23305, 23324.65, 0, 0, "13:35"], [23308, 23309, 23292.5, 23299.55, 0, 0, "13:36"]],
times = [array1, array2].reduce((r, array) => {
array.forEach(a => r[a[6]] ??= a)
return r;
}, {}),
result = timeArray
.sort()
.map(time => times[time] || [0, 0, 0, 0, 0, time]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I believe this is what you want
const base = ["13:37", "13:36", "13:35", "13:34", "13:33", "13:32"]
const arrayA = [
[23323.25,23323.65,23313.25,23315.05,97,62,"13:36"],
[23315.05,23315.2,23314,23315,8,9,"13:37"]
]
const arrayB = [
[23310,23310,23300,23300,0,0,"13:34"],
[23309.75,23343.1,23305,23323.25,0,0,"13:35"],
[23296.5,23310,23294.65,23309.8,0,0,"13:30"],
[23308.35,23310,23301,23306.15,0,0,"13:31"],
[23308,23309,23292.5,23299.55,0,0,"13:32"],
[23299.55,23310,23294.15,23310,0,0,"13:33"],
[23310,23310,23300,23300,0,0,"13:34"],
[23309.75,23343.1,23305,23324.65,0,0,"13:35"],
[23308,23309,23292.5,23299.55,0,0,"13:36"]
]
// const expectedResult = [
// [23308,23309,23292.5,23299.55,0,0,"13:32"],
// [23299.55,23310,23294.15,23310,0,0,"13:33"],
// [23310,23310,23300,23300,0,0,"13:34"],
// [23309.75,23343.1,23305,23324.65,0,0,"13:35"],
// [23323.25,23323.65,23313.25,23315.05,97,62,"13:36"],
// [23315.05,23315.2,23314,23315,8,9,"13:37"]
//]
const res = base.sort().map(time => {
return arrayA.find(subArray => subArray[subArray.length - 1] === time)
|| arrayB.find(subArray => subArray[subArray.length - 1] === time)
|| null
});
console.log(res);
I would modify the arrays in the following format to obtain a much faster access:
{
"13:34": [23310,23310,23300,23300,0,0]
}
Then find the appropriate array for each time item.
Code:
const timeArray = ["13:37", "13:36", "13:35", "13:34", "13:33", "13:32"]
const array1 = [
[23323.25,23323.65,23313.25,23315.05,97,62,"13:36"],
[23315.05,23315.2,23314,23315,8,9,"13:37"]
]
const array2 = [
[23310,23310,23300,23300,0,0,"13:34"],
[23309.75,23343.1,23305,23323.25,0,0,"13:35"],
[23296.5,23310,23294.65,23309.8,0,0,"13:30"],
[23308.35,23310,23301,23306.15,0,0,"13:31"],
[23308,23309,23292.5,23299.55,0,0,"13:32"],
[23299.55,23310,23294.15,23310,0,0,"13:33"],
[23310,23310,23300,23300,0,0,"13:34"],
[23309.75,23343.1,23305,23324.65,0,0,"13:35"],
[23308,23309,23292.5,23299.55,0,0,"13:36"]
]
const values1 = {}
array1.forEach(item => {
values1[item[6]] = item
})
const values2 = {}
array2.forEach(item => {
values2[item[6]] = item
})
const result = []
timeArray.sort().forEach(time => {
let itemResult = [0,0,0,0,0,0, time]
if (values1[time]) {
itemResult = values1[time]
} else if (values2[time]) {
itemResult = values2[time]
}
result.push(itemResult)
})
console.log(result)
in my opinion you can do like this
var finalarray = [];
for(var key in timeArray)
{
var timer = timeArray[key];
for(var key in array2)
{
arraytime2 = array2[key][6];
if(timer == arraytime2)
{
finalarray[arraytime2]=array2[key];
}
}
for(var key in array1)
{
arraytime1 = array1[key][6];
if(timer == arraytime1)
{
finalarray[arraytime1]=array1[key];
}
}
}
It is possible to use Map collection to have O(1) while mapping the items. So we can sort timeArray and then just map() items:
const unique_1 = new Map(array1.map(s => [s[6], s]));
const unique_2 = new Map(array2.map(s => [s[6], s]));
const result = timeArray
.sort()
.map(time => unique_1.get(time) || unique_2.get(time));
An example:
const timeArray = ["13:37", "13:36", "13:35", "13:34", "13:33", "13:32"]
const array1 = [
[23323.25, 23323.65, 23313.25, 23315.05, 97, 62, "13:36"],
[23315.05, 23315.2, 23314, 23315, 8, 9, "13:37"]
]
const array2 = [
[23310, 23310, 23300, 23300, 0, 0, "13:34"],
[23309.75, 23343.1, 23305, 23323.25, 0, 0, "13:35"],
[23296.5, 23310, 23294.65, 23309.8, 0, 0, "13:30"],
[23308.35, 23310, 23301, 23306.15, 0, 0, "13:31"],
[23308, 23309, 23292.5, 23299.55, 0, 0, "13:32"],
[23299.55, 23310, 23294.15, 23310, 0, 0, "13:33"],
[23310, 23310, 23300, 23300, 0, 0, "13:34"],
[23309.75, 23343.1, 23305, 23324.65, 0, 0, "13:35"],
[23308, 23309, 23292.5, 23299.55, 0, 0, "13:36"]
]
const unique_1 = new Map(array1.map(s => [s[6], s]));
const unique_2 = new Map(array2.map(s => [s[6], s]));
const result = timeArray
.sort()
.map(time => unique_1.get(time) || unique_2.get(time));
console.log(result)

How to extract key-value pairs from a object, on a particular string filter?

const obj = {
"pi_diagram": null,
"painting": null,
"heat_treatment": null,
"welding_procedure": null,
"inspection_test": null,
"pipecl_hadoop": null,
"pipecl": null,
"ludo_min_hadoop": null,
"ludo_min": 4,
"ludo_normal_hadoop": null,
"ludo_normal": 6,
"ludo_max_hadoop": null,
"ludo_max": null,
"ludo_test": null,
"ludo_mech_min": null,
"ludo_mech_max": null,
"ludo_unit": "barg",
"temp_min_hadoop": null
}
I am having this object , how to extract key value pair having '_hadoop' appended in key ??
you can refer this Q :
JavaScript: filter() for Objects
for your Q it would be as :
const obj = {
"pi_diagram": null,
"painting": null,
"heat_treatment": null,
"welding_procedure": null,
"inspection_test": null,
"pipecl_hadoop": null,
"pipecl": null,
"ludo_min_hadoop": null,
"ludo_min": 4,
"ludo_normal_hadoop": null,
"ludo_normal": 6,
"ludo_max_hadoop": null,
"ludo_max": null,
"ludo_test": null,
"ludo_mech_min": null,
"ludo_mech_max": null,
"ludo_unit": "barg",
"temp_min_hadoop": null
};
const filteredByKey = Object.fromEntries(Object.entries(obj).filter(([key, value]) => key.includes('_hadoop')))
console.log(filteredByKey);
const obj = {
"pi_diagram": null,
"painting": null,
"heat_treatment": null,
"welding_procedure": null,
"inspection_test": null,
"pipecl_hadoop": null,
"pipecl": null,
"ludo_min_hadoop": null,
"ludo_min": 4,
"ludo_normal_hadoop": null,
"ludo_normal": 6,
"ludo_max_hadoop": null,
"ludo_max": null,
"ludo_test": null,
"ludo_mech_min": null,
"ludo_mech_max": null,
"ludo_unit": "barg",
"temp_min_hadoop": null
}
let result = {}
for (const [key, value] of Object.entries(obj)) {
if (key.includes('_hadoop')) {
result[key] = value
}
}
console.log(result)
If you want to strictly check name ends with _hadoop and name doesn't contains _hadoop then you need to use regex like /_hadoop$/.test(propName).
Use Object.keys(obj) to get array of all keys of obj and then filter with /_hadoop$/.test(x) so it will return array of key ends with _hadoop.
Then use reduce to build your new object.
Check the result below.
const obj = {
"pi_hadoop_diagram": null,
"painting": null,
"heat_treatment": null,
"welding_procedure": null,
"inspection_test": null,
"pipecl_hadoop": null,
"pipecl": null,
"ludo_min_hadoop": null,
"ludo_min": 4,
"ludo_normal_hadoop": null,
"ludo_normal": 6,
"ludo_max_hadoop": null,
"ludo_max": null,
"ludo_test": null,
"ludo_mech_min": null,
"ludo_mech_max": null,
"ludo_unit": "barg",
"temp_min_hadoop": null
};
let result = Object.keys(obj)
.filter(x => /_hadoop$/.test(x))
.reduce((a, x) => (a[x] = obj[x], a), {});
console.log(result);

Javascript - Removing array values between a range

I want to remove all the null values between the first number and the end number.
My code seems far too complicated.
Love to see some more flexible minds at it.
let values = [null, null, null, 1, 2, null, 3, null, 4, null, null, 5, 6, 7, null, null, null, null];
let startIndex = values.findIndex(n => (n !== null))
let endIndex = values.length - 1;
for ( ; endIndex > 0; endIndex--) {
if (values[endIndex] !== null) break;
}
let arrayCopy = values.slice();
for(let i = endIndex; i > startIndex; i--) {
if (values[i] === null) {
arrayCopy.splice(i, 1);
}
}
console.log(arrayCopy)
Quick and dirty, sure it can be done better
var values = [null, null, null, 1, 2, null, 3, null, 4, null, null, 5, 6, 7, null, null, null, null];
var nonNull = values.filter(value => value !== null);
var result = [...values.slice(0, values.indexOf(nonNull[0])), ...nonNull, ...values.slice(values.lastIndexOf(nonNull[nonNull.length - 1]) + 1)];
console.log(result);
I used a filter taking index or null values into account, it is certainly clearer IMO.
If your array is "very large", it might be interesting to find another way to compute the endIndex, but if you don't have performance problems, I think you can keep this part of your code as it is.
let values = [null, null, null, 1, 2, null, 3, null, 4, null, null, 5, 6, 7, null, null, null, null];
let startIndex = values.findIndex(n => (n !== null))
let endIndex = values.length - 1;
for ( ; endIndex > 0; endIndex--) {
if (values[endIndex] !== null) break;
}
let arrayCopy = values.filter((v, i) => i < startIndex || i > endIndex || v !== null);
console.log(arrayCopy)
This approach use reduce function to find the number of nulls in the at the start and at the end of the array, and then to add counted nulls before and after the non null elements.
let values = [null, null, null, 1, 2, null, 3, null, 4, null, null, 5, 6, 7, null, null, null, null];
var reduceFn = function(a,b){
if (!a.finished && b === null){
a.nullCount++;
}
if (b !== null){
a.finished = true;
}
return a;
};
var start = {finished : false, nullCount:0};
values.reduce(reduceFn,start);
var end = {finished : false, nullCount:0};
values.slice().reverse().reduce(reduceFn,end);
result = Array(start.nullCount).fill(null);
result.push.apply(result,values.filter(v => v !== null));
result.push.apply(result,Array(end.nullCount).fill(null));
console.log(result)

Remove duplicate element in object and leave unique element

I have two object:
obj1
{
"uuid": "",
"open_bal_qty": 0,
"open_bal_value": 0,
"qty_min": 0,
"qty_med": 0,
"qty_max": 0,
"kedai_uuid": "198ceaef-4ced-4207-9ba0-62afbb42bb85"
}
obj2
{
"uuid": "",
"open_bal_qty": 0,
"open_bal_value": 0,
"kedai_uuid": "198ceaef-4ced-4207-9ba0-62afbb42bb85"
}
How can I remove duplicate and get element not exist in obj2 so my new obj will be:
newObj
{
"qty_min": 0,
"qty_med": 0,
"qty_max": 0,
}
I can use lodash pick but I dont want to manually entered the key name that I want to filter.
const newObj = pick(obj1, [
'qty_min',
'qty_med',
'qty_max',
]);
Thanks in advance.
With lodash you can _.omit() from obj1 all the _.keys() of obj2:
const obj1 = {"uuid":"","open_bal_qty":0,"open_bal_value":0,"qty_min":0,"qty_med":0,"qty_max":0,"kedai_uuid":"198ceaef-4ced-4207-9ba0-62afbb42bb85"};
const obj2 = {"uuid":"","open_bal_qty":0,"open_bal_value":0,"kedai_uuid":"198ceaef-4ced-4207-9ba0-62afbb42bb85"};
const newObj = _.omit(obj1, _.keys(obj2));
console.log(newObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Use for..in to iterate the object and Object.hasOwnProperty to check if the second object have the same key
var obj1 = {
"uuid": "",
"open_bal_qty": 0,
"open_bal_value": 0,
"qty_min": 0,
"qty_med": 0,
"qty_max": 0,
"kedai_uuid": "198ceaef-4ced-4207-9ba0-62afbb42bb85"
}
var obj2 = {
"uuid": "",
"open_bal_qty": 0,
"open_bal_value": 0,
"kedai_uuid": "198ceaef-4ced-4207-9ba0-62afbb42bb85"
}
var newObj = {};
for (var keys in obj1) {
if (!obj2.hasOwnProperty(keys)) {
newObj[keys] = obj1[keys]
}
}
console.log(newObj)
You could use _.pick in conjunction with _.difference by finding the difference between the two objects' keys and picking those keys:
const obj1 = {
"uuid": "",
"open_bal_qty": 0,
"open_bal_value": 0,
"qty_min": 0,
"qty_med": 0,
"qty_max": 0,
"kedai_uuid": "198ceaef-4ced-4207-9ba0-62afbb42bb85"
};
const obj2 = {
"uuid": "",
"open_bal_qty": 0,
"open_bal_value": 0,
"kedai_uuid": "198ceaef-4ced-4207-9ba0-62afbb42bb85"
};
const obj1Keys = _.keys(obj1); //or Object.keys
const obj2Keys = _.keys(obj2);
console.log(_.pick(obj1Keys > obj2Keys ? obj1 : obj2, _.difference(obj1Keys, obj2Keys)))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

Can't print a value in JS object

I'm trying to print a value stored in a JS object but I don't know how can I access it. Here's my code:
var the_votes = {
"Heredia": {
voters: 70000,
parties: {
pln: 0,
pac: 0,
plib: 0,
rc: 0
}
},
"San Jose": {
voters: 200000,
parties: {
pln: 0,
pac: 0,
plib: 0,
rc: 0
}
},
"Alajuela": {
voters: 80000,
parties: {
pln: 0,
pac: 0,
plib: 0,
rc: 0
}
},
"Cartago": {
voters: 50000,
parties: {
pln: 0,
pac: 0,
plib: 0,
rc: 0
}
},
"Puntarenas": {
voters: 100000,
parties: {
pln: 0,
pac: 0,
plib: 0,
rc: 0
}
},
"Limon": {
voters: 60000,
parties: {
pln: 0,
pac: 0,
plib: 0,
rc: 0
}
},
"Guanacaste": {
voters: 90000,
parties: {
pln: 0,
pac: 0,
plib: 0,
rc: 0
}
}
};
And I want to print the value "voters" on the console with this method:
function updateTable(votes) {
table_clear();
var table = $("#elections");
var tbody = table.append($("<tbody/>"));
$.each(votes, function (province, data) {
var row = $("<tr/>");
row.append($("<td/>")).html(province);
$.each(data.parties, function (partyName, partyValue) {
var td = $("<td/>");
td.html(partyValue);
row.append(td);
td = $("<td/>");
td.html();
console.log(province.voters);
row.append(td);
});
tbody.append(row);
});
};
I keep getting an "undefined" on this line: "console.log(province.voters);
How can I access the value under this method structure?
province is a string. It doesn't have a property voters.
data is the object you want to access (which you already do correctly for data.parties):
console.log(data.voters);
you want to console.log(data.voters);
province is simply the string identifier such as "Puntarenas"
alternatively you could do console.log(votes[province].voters);
To print voters for every province:
console.log(data.voters);
console.log(the_votes.Heredia.voters)
This will print voters in "Heredia"

Categories

Resources