Convert specific json elements to number in json - javascript

I have the following json object:
[{
"WEIGHTED_ARR_LAST_SLP": "0.03801186624130076",
"SLIPPAGE_INTERVAL_VWAP_BPS": "10.2711",
"ROOT_ORDER_ID": "735422197553491",
"ARRIVAL_MID_PX": "93.6100",
"WEIGHTED_ARR_SLP": "0.12323190317127024",
"AVG_PX": "93.6586",
"LEAVES_QTY": "0",
"WEIGHT": "0.02372627566400397",
"PARTICIPATION_RATE": "0E-12",
"LOCAL_REF_END_TIME": "2016-09-06 06:00:27.775",
"WEIGHTED_IVWAP_SLP": "0.2436949499725512",
"NOTIONAL_USD": "477940",
"LIQ_CONSUMPTION": "15.21",
"EXEC_QTY": "5103",
"CL_ORD_ID": "7245294057012908344",
"LOCAL_REF_START_TIME": "2016-09-06 05:59:57.844",
"SLIPPAGE_END_LAST_ARR_LAST_BPS": "1.6021",
"IVWAP_PX": "93.5625",
"LIMIT_PX": "93.6100",
"ORDER_ID": "735422197553491",
"SLIPPAGE_ARR_MID_BPS": "5.1939",
"ORDER_QTY": "5103",
"EXECUTION_STYLE": "2", {"ORDER_QTY": "5100", ..........}
}]
I want to coonvert only "Ord Qty", "Exec Qty", "AVG Px", "Notional", "Limit Px", "Arrival Px" "Arrival Px Slpg", "IVWAP Px Slpg", "LIQ Consumption" to Number; and then display WEIGHTED_IVWAP_SLP & WEIGHTED_ARR_SLP with 4 decimal points, instead of so many. I'm trying to do it in the following way:
var jsondata = document.getElementById("jsonArray").value;
var jsondataObj = JSON.parse(jsondata);
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
var parsedData = jsondataObj.map(function(obj) {
return Object.keys(obj).reduce(function(memo, key) {
var value = obj[key];
//console.log(value);
memo[key] = isNumeric(value) ? Number(value).toFixed(4) : value;
//localStorage.setItem("storeditem", value);
return memo;
}, {})
});
But this is converting all of fields of numbers with 4 decimal point. How to convert only specific fields?

This is kind of doing your job for you right? Well, this answer doesn't use your code, but you should be able to apply it just the same. This uses language constructs such as if, for and for ... in as opposed to methods of Array like map, reduce, and filter.
var a = [{
"WEIGHTED_ARR_LAST_SLP": "0.03801186624130076",
"SLIPPAGE_INTERVAL_VWAP_BPS": "10.2711",
"ROOT_ORDER_ID": "735422197553491",
"ARRIVAL_MID_PX": "93.6100",
"WEIGHTED_ARR_SLP": "0.12323190317127024",
"AVG_PX": "93.6586",
"LEAVES_QTY": "0",
"WEIGHT": "0.02372627566400397",
"PARTICIPATION_RATE": "0E-12",
"LOCAL_REF_END_TIME": "2016-09-06 06:00:27.775",
"WEIGHTED_IVWAP_SLP": "0.2436949499725512",
"NOTIONAL_USD": "477940",
"LIQ_CONSUMPTION": "15.21",
"EXEC_QTY": "5103",
"CL_ORD_ID": "7245294057012908344",
"LOCAL_REF_START_TIME": "2016-09-06 05:59:57.844",
"SLIPPAGE_END_LAST_ARR_LAST_BPS": "1.6021",
"IVWAP_PX": "93.5625",
"LIMIT_PX": "93.6100",
"ORDER_ID": "735422197553491",
"SLIPPAGE_ARR_MID_BPS": "5.1939",
"ORDER_QTY": "5103",
"EXECUTION_STYLE": "2"
}];
var fieldsToConvertToNumbers = [
"ORDER_QTY", "EXEC_QTY", "AVG_PX",
"NOTIONAL_USD", "LIMIT_PX", "ARRIVAL_MID_PX",
"WEIGHTED_IVWAP_SLP", "LIQ_CONSUMPTION"
];
for (var i = 0; i < a.length; ++i) {
var b = a[i];
for (var j = 0; j < fieldsToConvertToNumbers.length; ++j) {
var field = fieldsToConvertToNumbers[j];
if (field in b) {
var value = parseFloat(b[field]);
if (!isNaN(value))
b[field] = value;
}
}
}
var pre = document.createElement("pre");
pre.appendChild(document.createTextNode(JSON.stringify(a, null, ' ')));
document.body.appendChild(pre);
Use parseFloat to convert the values to numbers, but be sure to check for NaN results before deciding to update the value. Use IsNaN for that. Don't think you really need to use !IsFinite, but knock yourself out.
So now you want to use toFixed to fix your string display.
var text = (3.1415926535897932384626433832795028841971).toFixed(4);
var pre = document.createElement("pre");
pre.appendChild(document.createTextNode(text));
document.body.appendChild(pre);
So now you can use toFixed to convert your numbers to strings that have only 4 decimal places of precision. However, they are strings instead of numbers. So you have to parse them back using parseFloat.
var a = [{
"WEIGHTED_ARR_LAST_SLP": "0.03801186624130076",
"SLIPPAGE_INTERVAL_VWAP_BPS": "10.2711",
"ROOT_ORDER_ID": "735422197553491",
"ARRIVAL_MID_PX": "93.6100",
"WEIGHTED_ARR_SLP": "0.12323190317127024",
"AVG_PX": "93.6586",
"LEAVES_QTY": "0",
"WEIGHT": "0.02372627566400397",
"PARTICIPATION_RATE": "0E-12",
"LOCAL_REF_END_TIME": "2016-09-06 06:00:27.775",
"WEIGHTED_IVWAP_SLP": "0.2436949499725512",
"NOTIONAL_USD": "477940",
"LIQ_CONSUMPTION": "15.21",
"EXEC_QTY": "5103",
"CL_ORD_ID": "7245294057012908344",
"LOCAL_REF_START_TIME": "2016-09-06 05:59:57.844",
"SLIPPAGE_END_LAST_ARR_LAST_BPS": "1.6021",
"IVWAP_PX": "93.5625",
"LIMIT_PX": "93.6100",
"ORDER_ID": "735422197553491",
"SLIPPAGE_ARR_MID_BPS": "5.1939",
"ORDER_QTY": "5103",
"EXECUTION_STYLE": "2"
}];
var fieldsToConvertToNumbers = [
"ORDER_QTY", "EXEC_QTY", "AVG_PX",
"NOTIONAL_USD", "LIMIT_PX", "ARRIVAL_MID_PX",
"LIQ_CONSUMPTION"
];
var fieldsToConvertToFixedNumbers = [
"WEIGHTED_IVWAP_SLP", "WEIGHTED_ARR_SLP"
];
for (var i = 0; i < a.length; ++i) {
var b = a[i];
for (var j = 0; j < fieldsToConvertToNumbers.length; ++j) {
var field = fieldsToConvertToNumbers[j];
if (field in b) {
var value = parseFloat(b[field]);
if (!isNaN(value))
b[field] = value;
}
}
for (var j = 0; j < fieldsToConvertToFixedNumbers.length; ++j) {
var field = fieldsToConvertToFixedNumbers[j];
if (field in b) {
var value = parseFloat(b[field]);
if (!isNaN(value))
b[field] = parseFloat(value.toFixed(4));
}
}
}
var pre = document.createElement("pre");
pre.appendChild(document.createTextNode(JSON.stringify(a, null, ' ')));
document.body.appendChild(pre);
So now only the specific fields have 4 decimal places. And they're numbers, not strings.

You can modify your code slightly by adding a filter on the keys, before launching the reduce(). Secondly, you could put an extra condition in your ternary operator, to deal with the two fields that should get 4 decimal digits:
var parsedData = jsondataObj.map(function(obj) {
return Object.keys(obj).filter (
key => ["ORDER_QTY", "EXEC_QTY", "AVG_PX", "NOTIONAL_USD", "LIMIT_PX",
"ARRIVAL_MID_PX", "WEIGHTED_ARR_SLP", "WEIGHTED_IVWAP_SLP",
"LIQ_CONSUMPTION"].includes(key)
).reduce(function(memo, key) {
var value = obj[key];
memo[key] = !isNumeric(value) ? value
: ["WEIGHTED_IVWAP_SLP", "WEIGHTED_ARR_SLP"].includes(key)
? Number(value).toFixed(4)
: Number(value);
return memo;
}, Object.assign({}, obj))
});
Note that you must then also pass a copy of the original object as initial value for reduce. For this Object.assign can be used.
Also, be aware that .toFixed turns a number back to string type, as this is the only way to actually ensure you see 4 decimal digits. If you want to really have the number type, then apply Number() to that result again:
Number(Number(value).toFixed(4))
Of course, trailing decimal zeroes will not display when you output such numbers without formatting.
var jsondata = `[{
"WEIGHTED_ARR_LAST_SLP": "0.03801186624130076",
"SLIPPAGE_INTERVAL_VWAP_BPS": "10.2711",
"ROOT_ORDER_ID": "735422197553491",
"ARRIVAL_MID_PX": "93.6100",
"WEIGHTED_ARR_SLP": "0.12323190317127024",
"AVG_PX": "93.6586",
"LEAVES_QTY": "0",
"WEIGHT": "0.02372627566400397",
"PARTICIPATION_RATE": "0E-12",
"LOCAL_REF_END_TIME": "2016-09-06 06:00:27.775",
"WEIGHTED_IVWAP_SLP": "0.2436949499725512",
"NOTIONAL_USD": "477940",
"LIQ_CONSUMPTION": "15.21",
"EXEC_QTY": "5103",
"CL_ORD_ID": "7245294057012908344",
"LOCAL_REF_START_TIME": "2016-09-06 05:59:57.844",
"SLIPPAGE_END_LAST_ARR_LAST_BPS": "1.6021",
"IVWAP_PX": "93.5625",
"LIMIT_PX": "93.6100",
"ORDER_ID": "735422197553491",
"SLIPPAGE_ARR_MID_BPS": "5.1939",
"ORDER_QTY": "5103",
"EXECUTION_STYLE": "2"
}]`;
var jsondataObj = JSON.parse(jsondata);
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
var parsedData = jsondataObj.map(function(obj) {
return Object.keys(obj).filter (
key => ["ORDER_QTY", "EXEC_QTY", "AVG_PX", "NOTIONAL_USD", "LIMIT_PX",
"ARRIVAL_MID_PX", "WEIGHTED_ARR_SLP", "WEIGHTED_IVWAP_SLP",
"LIQ_CONSUMPTION"].includes(key)
).reduce(function(memo, key) {
var value = obj[key];
memo[key] = !isNumeric(value) ? value
: ["WEIGHTED_IVWAP_SLP", "WEIGHTED_ARR_SLP"].includes(key)
? Number(value).toFixed(4)
: Number(value);
return memo;
}, Object.assign({}, obj))
});
console.log(parsedData);

Here you have a practical example:
var x = {
a: '1.11111',
b: '2.22222',
c: '3.33333',
d: '4.444444',
e: '5.55555'
}
var y = ['a', 'd'];
for(key in x) {
if(y.indexOf(key) != -1) {
x[key] = Number(x[key]).toFixed(2);
}
}
console.log(x);
X is your object and Y is an array containing the list of keys you want to convert to fixed, or whatever you want to do.
When going through the keys, if the key is inside that array, you do your thing.
https://jsfiddle.net/dtuLxzy6/

Related

Thousands separator for integers in javascript

I have the following
How do I convert OrderID to thousands separator i.e., 100,000??
I'm doing it this way but it's not working:
var thousandseparator = [
"QRDER_QTY", "EXEC_QTY", "AVG_PX", "NOTIONAL_USD", "LIMIT_PX", "LIQ_CONSUMPTION"
];
for(var i = 0; i < json.length; i++) {
var obj = json[i];
for(key in obj) {
if(thousandseparator.indexOf(key) != -1) {
obj[key] = Number(obj[key].toString().toLocaleString());
}
}
}
Also, I'm converting each element to integer like this:
var jsondata = document.getElementById("jsonArray").value;
var json = JSON.parse(jsondata);
var parsedData = json.map(function(obj) {
return Object.keys(obj).reduce(function(memo, key) {
var value = obj[key];
//console.log(value);
memo[key] = isNumeric(value) ? Number(value) : value;
//localStorage.setItem("storeditem", value);
return memo;
}, {})
});
But on doing so, the decimals like 2.40 are converted to 2.4. How do I make it 2.40 only??
Here is how to use toLocaleString() (I've cut down your sample to just the essentials)
var obj = {
"ROOT_ORDER_ID": "735422197553491",
"AVG_PX": "93.6586",
"NOTIONAL_USD": "477940",
"LIQ_CONSUMPTION": "15.21",
"EXEC_QTY": "5103",
"LIMIT_PX": "93.6100",
"ORDER_QTY": "5103"
}
var thousandseparator = [
"ORDER_QTY", "EXEC_QTY", "AVG_PX", "NOTIONAL_USD", "LIMIT_PX", "LIQ_CONSUMPTION"
];
for(key in obj) {
if(thousandseparator.indexOf(key) != -1) {
obj[key] = Number(obj[key]).toLocaleString();
}
}
console.log(obj)
You want to use it on a number, hence you first want to do Number(obj[key]) and then call .toLocaleString() on the result, however your code was doing the operation in reverse.
As for your second question - you cannot have a formatted numeric value. JavaScript shows numbers in the most "convenient" way possible, although that's not the best way. In general, any extra zeroes in the fractional part will be hidden and numbers that are too long will be shortened to scientific notation (for example 1e24).
If you want to display numeric data formatted, it would have to be done as a string. If you want to show an exact number of decimal places, then use Number#toFixed() which returns a string:
var pi = 3.141592;
console.log(pi, typeof pi);
var shortPi = pi.toFixed(2);
console.log(shortPi, typeof shortPi);
var money = 3.50;
console.log(money, typeof money);
var formattedMoney = money.toFixed(2);
console.log(formattedMoney, typeof formattedMoney);
Try replacing:
obj[key] = Number(obj[key].toString().toLocaleString());
with:
obj[key] = Number(obj[key]).toLocaleString();

Filter unique array values and sum values

I have the following js array:
for(var j = 0; j < array.length; j++){
arr.push([array[j][0],array[j][1],array[j][2]]);
}
And it translates into this:
Number, type, qty
[[12345, "product", "10"],[12345, "product", "15"],[1234567, "other", "10"]]
What I've been trying to do is to filter the unique product number array[j][0] and sum the qty array[j][2] if there's more than one and I was able to do the unique filter by doing the following:
for(var o = 0; o < arr.length; o++){
if (!n[arr[o][1]]){
n[arr[o][1]] = true
r.push(arr[o]);
}
}
I would like your help to figure this out.. What I'm expecting to achieve is something like this:
[[12345, "product", "25"],[1234567, "other", "10"]]
Since product 12345 was repeated I only need to display it once and sum the qty of the other products with the same product number.
var productIndex = {};
var result = [];
for (var i = 0; i < arr.length; i++) {
var productId = arr[i][0];
if (productIndex[productId] === undefined) {
productIndex[productId] = result.length;
result.push(arr[i]);
} else {
var index = productIndex[productId];
result[index][2] = String(+result[index][2] + +arr[i][2]);
}
}
I am sure there are better ways. But I just changed it to an object, added them and changed it back to an array. Here you go:
https://jsfiddle.net/ct6to1Lv/
var a = [[12345, "product", "10"],[12345, "product", "15"],[1234567, "other", "10"]];
var b = {};
var c = [];
for(var i = 0; i < a.length; i++) {
if(!b.hasOwnProperty(a[i][0])) {
b[a[i][0]] = {};
b[a[i][0]]['qty'] = 0;
}
b[a[i][0]]['id'] = a[i][0];
b[a[i][0]]['name'] = a[i][1];
b[a[i][0]]['qty'] += parseInt(a[i][2]);
}
for(key in b) {
c[c.length] = [b[key]['id'], b[key]['name'], b[key]['qty']];
}
$(function(){
$('#console').append(a.toString()+'<br />');
$('#console').append(JSON.stringify(b)+'<br />');
$('#console').append(c.toString());
});
var arr = [[12345, "product", "10"],[12345, "product", "15"],[1234567, "other", "10"]];
var obj = {};
arr.forEach(function(e){
var t = e[0];
if(obj[t]) {
obj[t][2] += +e[2];
} else {
t = [];
t[0] = e[0];
t[1] = e[1];
t[2] = +e[2];
obj[e[0]] = t;
}
});
var res = [];
Object.keys(obj).forEach(function(k) {
res.push(obj[k]);
});
console.log(res);
Result:
[ [ 12345, 'product', 25 ], [ 1234567, 'other', 10 ] ]
To complete the possibillities, here a solution with a temporary object, which is hidden in this.
var data = [[12345, "product", "10"], [12345, "product", "15"], [1234567, "other", "10"]],
result = function (data) {
var r = [];
data.forEach(function (a) {
if (!this[a[0]]) {
this[a[0]] = [a[0], a[1], 0];
r.push(this[a[0]]);
}
this[a[0]][2] += +a[2];
}, {});
return r;
}(data);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
See Array.prototype.reduce() and Array.prototype.sort()
var list = [[12345, "product", "10"], [12345, "product", "15"], [1234567, "other", "10"], [12345, "product", "5"]];
//first we sort the array by id
//#pv = previous value; #cv = current value
list.sort(function(pv, cv) {
var a = +pv[0],
b = +cv[0];
return a - b;
});
//reduce the array for repeated elements
//#pv = previous value; #cv = current value
var reduced = list.reduce(function (pv, cv) {
//slice keeps reference when element is an object/array
var last = pv.slice(-1)[0];
if (last === undefined) return [cv];
//compares the id
if (last[0] == cv[0])
last[2] = +last[2] + (+cv[2]); //sums values
else pv.push(cv); //order elements
return pv;
}, []); //[] initial value for #pv
console.log(reduced);

Need help building a javascript array from given object values.

This is an object that I have.
var MyObject = {
'stop1-start': "0",
'stop1-color': "#0074a2",
'stop2-start': "32",
'stop2-color': "#ff6600"
};
this is an array that I need.
var newArray =[
{
'stop-start': "0",
'stop-color': "#0074a2",
},
{
'stop-start': "32",
'stop-color': "#ff6600",
}
];
I tried for loops, jquery each but just cant wrap my head around it.
Any help is appreciated.
You should figure out which numbers are present first, for safety's sake, then turn each pair into a record. Like so:
var MyObject = {
'stop1-start': "0",
'stop1-color': "#0074a2",
'stop2-start': "32",
'stop2-color': "#ff6600"
};
function createArray(data) {
// Figure out which numbers are present
var numbers = Object.keys(data).map(function(key) {
return parseInt(key.match(/stop(\d+)/)[1], 10);
});
// Filter out duplicates
numbers = numbers.filter(function (num, idx, arr) {
// Only take the first instance of each value
return arr.indexOf(num) === idx;
}).sort();
// For each number, create a record
var records = numbers.map(function(num) {
var start = 'stop' + num + '-start';
var color = 'stop' + num + '-color';
return {
start: data[start],
color: data[color]
};
});
return records;
}
document.getElementById('r').textContent = JSON.stringify(createArray(MyObject));
<pre id=r></pre>
If you want to get all clever and functional, you can turn the whole algorithm into a single chain:
function createArray(data) {
// Figure out which numbers are present
return Object.keys(data).map(function(key) {
return parseInt(key.match(/stop(\d+)/)[1], 10);
}).filter(function (num, idx, arr) {
// Only take the first instance of each value
return arr.indexOf(num) === idx;
}).sort().map(function(num) {
var start = 'stop' + num + '-start';
var color = 'stop' + num + '-color';
return {
start: data[start],
color: data[color]
};
});
}
If you have access to ES6, you can use that for some shorthand:
function createArray(data) {
return Object.keys(data)
.map(key => parseInt(key.match(/stop(\d+)/)[1], 10))
.filter((num, idx, arr) => arr.indexOf(num) === idx)
.sort()
.map(num => {
return {
start: data[`stop${num}-start`],
color: data[`stop${num}-color`]
};
});
}
Object keys are not guaranteed to be in order, so you'll need to find the array's index within the key itself:
var MyObject = {
'stop1-start': "0",
'stop1-color': "#0074a2",
'stop2-start': "32",
'stop2-color': "#ff6600"
};
var newArray= [];
Object.keys(MyObject).sort().forEach(function(key) {
var num= key.match(/(\d+)/)[0] - 1;
newArray[num] = newArray[num] || {};
newArray[num][key.replace(num+1,'')]= MyObject[key];
});
document.body.innerHTML= JSON.stringify(newArray);
Try:
var newArray = [], current = {}, i = 0;
for(var key in MyObject){
current[i % 2 ? "stop-color" : "stop-start"] = MyObject[key];
i++ % 2 && (newArray.push(current), current = {})
}
Demo

Compare two JSON arrays in JQuery or Javascript

Using jQuery - I would like to compare 2 JSON arrays:
origArray comes from the database/C# API:
var origArray = [ {
"TypeName": "Single",
"TypeID": "3121",
"TypeCount": "2"
},
{
"TypeName": "Double",
"TypeID": "4056",
"TypeCount": "2"
},
{
"TypeName": "Family",
"TypeID": "5654",
"TypeCount": "4"
}
];
userArray is gathered from user input:
var userArray = [ {
"TypeID": "3121",
"TypeCount": "2"
},
{
"TypeID": "4056",
"TypeCount": "3"
},
{
"TypeID": "3121",
"TypeCount": "3"
}
];
What I would like to do, is loop through the userArray, and "group" by the TypeID, and Sum the TypeCount.
So in the example above:
TypeID: 3121
TypeCount: 5 (ie. 2 + 3)
TypeID: 4056
TypeCount: 3
Meaning there would be a difference of 3 over for TypeID 3121 and 1 over for 4056.
Is there any way of getting that information out of either jQuery or native Javascript (that would work cross-browser)?
Thanks for any help,
Mark
Define a function to group by each array by TypeID and sum TypeCount:
function groupByTypeID (arr) {
var groupBy = {};
$.each(arr, function () {
var currentCount = groupBy[this.TypeID] || 0;
groupBy[this.TypeID] = currentCount + parseInt(this.TypeCount);
});
return groupBy;
}
Then, group both arrays, and take their differences:
var userArrayGroups = groupByTypeID(userArray);
var origArrayGroups = groupByTypeID(origArray);
var diff = {};
for (var prop in userArrayGroups) {
diff[prop] = userArrayGroups[prop] - origArrayGroups[prop];
}
diff will then hold the following:
{
3121: 3
4056: 1
}
DEMO.
If you are familiar with C# this js library - linqjs.
It contains implementations of all .NET 4.0 LINQ methods and many extra methods.
You can do it with Underscore:
var result = _.chain(userArray)
.groupBy(function(value) {
// group by the TypeId
return value.TypeID;
})
.map(function(value) {
// iterate over every group
var addition = _.chain(value)
.pluck("TypeCount") // create an array with TypeCount values
.reduce(function(memo, num) {
return Number(memo) + Number(num); // add all the TypeCount values
})
.value();
return {
"TypeID": value[0].TypeID, // TypeID
"TypeCount": addition // total addition for this TypeID
};
})
.value();
Working example here: http://livecoding.io/3498441
I'll have a shot at it...
var mergeArray = []
var index;
for (var i = userArray.length - 1; i >= 0; i--) {
index = findByTypeID(mergeArray, userArray[i].TypeID);
if(!index){
mergeArray[index].TypeCount += parseInt(userArray[i].TypeCount)
} else{
mergeArray.push({
"TypeID": userArray[i].TypeID,
"TypeCount": parseInt(userArray[i].TypeCount)
});
}
};
function findByTypeID(arr, id){
for (var i = arr.length - 1; i >= 0; i--) {
if(arr[i].TypeID == id)
return i;
};
return -1;
}
This gives you your desired data structure output inside mergeArray
result = {};
for (var i in userArray) {
var elem = userArray[i]
if (!result[elem.TypeID])
result[elem.TypeID] = elem.TypeCount;
else
result[elem.TypeID] += elem.TypeCount;
}
return result;

Count duplicates within an Array of Objects

I have an array of objects as follows within my server side JS:
[
{
"Company": "IBM"
},
{
"Person": "ACORD LOMA"
},
{
"Company": "IBM"
},
{
"Company": "MSFT"
},
{
"Place": "New York"
}
]
I need to iterate through this structure, detect any duplicates and then create a count of a duplicate is found along side each value.
Both of the values must match to qualify as a duplicate e.g. "Company": "IBM" is not a match for "Company": "MSFT".
I have the options of changing the inbound array of objects if needed. I would like the output to be an object, but am really struggling to get this to work.
EDIT: Here is the code I have so far where processArray is the array as listed above.
var returnObj = {};
for(var x=0; x < processArray.length; x++){
//Check if we already have the array item as a key in the return obj
returnObj[processArray[x]] = returnObj[processArray[x]] || processArray[x].toString();
// Setup the count field
returnObj[processArray[x]].count = returnObj[processArray[x]].count || 1;
// Increment the count
returnObj[processArray[x]].count = returnObj[processArray[x]].count + 1;
}
console.log('====================' + JSON.stringify(returnObj));
For example:
counter = {}
yourArray.forEach(function(obj) {
var key = JSON.stringify(obj)
counter[key] = (counter[key] || 0) + 1
})
Docs: Array.forEach, JSON.stringify.
Object.prototype.equals = function(o){
for(var key in o)
if(o.hasOwnProperty(key) && this.hasOwnProperty(key))
if(this[key] != o[key])
return false;
return true;
}
var array = [/*initial array*/],
newArray = [],
ok = true;
for(var i=0,l=array.length-1;i<l;i++)
for(var j=i;j<l+1;j++)
{
if(!array[i].equals(array[j]))
newArray.push(array[i]);
}
We are required to write a JavaScript function that takes in one such array of objects. The function creates and return a new array in which no objects are repeated (by repeated we mean objects having same value for "Country" property.)
Moreover, the function should assign a count property to each object that represents the number of times they appeared in the original array.
const arr = [
{
"Country": "BR",
"New Lv1−Lv2": "#N/A"
},
{
"Country": "BR",
"New Lv1−Lv2": "#N/A"
},
{
"Country": "",
"New Lv1−Lv2": "test"
}];
const convert = (arr) => {
const res = {};
arr.forEach((obj) => {
const key = `${obj.Country}${obj["New Lv1−Lv2"]}`;
if (!res[key]) {
res[key] = { ...obj, count: 0 };
};
res[key].count += 1;
});
return Object.values(res);
};
console.log(convert(arr));
know more
With ES6, one can use Array#reduce with an object to store the counts.
let counts = arr.reduce((acc, curr)=>{
const str = JSON.stringify(curr);
acc[str] = (acc[str] || 0) + 1;
return acc;
}, {});
Demo
To create a new array without duplicates, a Set can be used with Array#filter.
let set = new Set;
let res = arr.filter(x => {
const str = JSON.stringify(x);
return !set.has(str) && set.add(str);
});
Demo

Categories