I have two JSON arrays with same fields as follows:
var total_90 = [
{ "date": "2011-11-14T17:22:59Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T17:07:21Z", "quantity": 2, "total": 90, "tip": 1, "type": "tab" },
{ "date": "2012-11-14T16:30:43Z", "quantity": 3, "total": 90, "tip": 0, "type": "tab" }
];
var tip_0 = [
{ "date": "2011-11-14T17:22:59Z", "quantity": 2, "total": 80, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T17:07:21Z", "quantity": 2, "total": 70, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T16:58:03Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T16:30:43Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" }
];
I need a third JSON file which has the intersection of the above two JSON files. (By intersection, I mean all the rows from both the JSON files which have TOTAL=90 AND TIP=0)
Is there some way to do this?
My expected output will be a third JSON file with the following output
{"date":"2012-11-14T16:30:43Z","quantity":3,"total":90,"tip":0,"type":"tab"},
{"date":"2011-11-14T16:58:03Z","quantity":2,"total":90,"tip":0,"type":"tab"},
{"date":"2011-11-14T16:30:43Z","quantity":2,"total":90,"tip":0,"type":"tab"}
You need to loop the 2 objects and merge the contents into 1 object.
For examples check this thread since this is a duplicate How can I merge properties of two JavaScript objects dynamically?
You could do the following to collect all the rows from both the JSON files which have TOTAL = 90 and TIP = 0 -
var total_90 = [
{ "date": "2011-11-14T17:22:59Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T17:07:21Z", "quantity": 2, "total": 90, "tip": 1, "type": "tab" },
{ "date": "2012-11-14T16:30:43Z", "quantity": 3, "total": 90, "tip": 0, "type": "tab" }
];
var tip_0 = [
{ "date": "2011-11-14T17:22:59Z", "quantity": 2, "total": 80, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T17:07:21Z", "quantity": 2, "total": 70, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T16:58:03Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T16:30:43Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" }
];
// An empty arrays to contain final intersection array
var result = [];
/* now looping over both arrays to traverse all the elements from them */
// iterating over first array
total_90.forEach(x => {
// iterating over second array
tip_0.forEach(y => {
// push into output array only if total is 90 & tip is 0
if ((x.total == 90 && y.total == 90) && (x.tip == 0 && y.tip == 0)) {
result.push({
date: x.date,
quantity: x.quantity,
total: x.total,
tip: x.tip,
type: x.type
});
}
});
});
console.log(result);
Note - this can be optimized to reduce the time complexity.
function intersection(a, b)
{
var result = [];
for (var i = 0; i < a.length; i++){
if (a[i].total == 90 && a[i].tip == 0)
{
result.push(a[i]);
}
}
for (var i = 0; i < b.length; i++){
if (b[i].total == 90 && b[i].tip == 0)
{
result.push(b[i]);
}
}
return result;
}
JSFiddle
EDIT: Update the function with the use of concat to provide a slightly more short hand.
function intersection(a, b)
{
var result = [];
var c = a.concat(b);
for (var i = 0; i < c.length; i++){
if (c[i].total == 90 && c[i].tip == 0)
{
result.push(c[i]);
}
}
return result;
}
New JSFiddle
var total_90 = [
{"date":"2011-11-14T17:22:59Z","quantity":2,"total":90,"tip":0,"type":"tab"},
{"date":"2011-11-14T17:07:21Z","quantity":2,"total":90,"tip":1,"type":"tab"},
{"date":"2012-11-14T16:30:43Z","quantity":3,"total":90,"tip":0,"type":"tab"}
]
var tip_0 = [
{"date":"2011-11-14T17:22:59Z","quantity":2,"total":80,"tip":0,"type":"tab"},
{"date":"2011-11-14T17:07:21Z","quantity":2,"total":70,"tip":0,"type":"tab"},
{"date":"2011-11-14T16:58:03Z","quantity":2,"total":90,"tip":0,"type":"tab"},
{"date":"2011-11-14T16:30:43Z","quantity":2,"total":90,"tip":0,"type":"tab"}
]
allData['total_90'] = total_90;
allData['tip_0'] = tip_0;
use allData
Related
I'm trying to compare this array of object :
"platforms": [
{
"id": 1,
"name": "KF",
"bankAccounts": [
{
"id": 22,
"balance": -100,
"lendingPlatformId": 3
},
{
"id": 27,
"balance": 500,
"lendingPlatformId": 4
}
],
},
{
"id": 3,
"name": "CC",
"bankAccounts": [
{
"id": 23,
"balance": 100,
"lendingPlatformId": 1
}
],
},
{
"id": 4,
"name": "DD",
"bankAccounts": [
{
"id": 28,
"balance": 0,
"lendingPlatformId": 1
}
],
}
]
I want to compare the platform[].id and match bankAccounts[].lendingPlatformId
for example:
bankAccounts[].id = 22, its lendingPlatformId = 3, so it need to find platform[].id = 3 and bankAccounts[].id = 23 and lendingPlatformId = 1 ,then compare their balance's sum is equal to zero, than push to new array.
expecting result is one new array:
isEqualToZero = [true, false, true, false]
(order is matter)
I'm thinking make it new object like:
platofmrId = 1 :{ lendingPlatformId: 3, balance:100 }, {lendingPlatformId: 4, balance:500 }
platofmrId = 3 :{ lendingPlatformId: 1, balance:-100 }
but seems it can't achieve what i want
i've no idea how to do it...
please help, Thanks!
const res=[] //to save result
platforms.forEach(platform=>{ //go through platforms
platform.bankAccounts.forEach(bank=>{ //go through platform bank account
// to get lendingPlatform
const lendPlatform=platforms.find(p=>p.id==bank.lendingPlatformId);
//add the balance and compare
if((lendPlatform.bankAccounts[0].balance+bank.balance)==0)
res.push(true) // if combined balance is zero
else
res.push(false)
})})
console.log(res)
const platforms = [
{
"id": 1,
"name": "KF",
"bankAccounts": [
{
"id": 22,
"balance": -100,
"lendingPlatformId": 3
},
{
"id": 27,
"balance": 500,
"lendingPlatformId": 4
}
]
},
{
"id": 3,
"name": "CC",
"bankAccounts": [
{
"id": 23,
"balance": 100,
"lendingPlatformId": 1
}
]
},
{
"id": 4,
"name": "DD",
"bankAccounts": [
{
"id": 28,
"balance": 0,
"lendingPlatformId": 1
}
]
}
];
const emptyArrayInit = Array.from(new Array(4), ()=>[0,0,0,0])
platforms.forEach(platform=>{
const {id, bankAccounts}=platform;
const index = id-1;
bankAccounts.forEach(bankAccount=>{
const {balance,lendingPlatformId } =bankAccount;
const lendingPlatformIdIndex = lendingPlatformId-1;
if(balance>0){
emptyArrayInit[index][lendingPlatformIdIndex] += balance;
}else{
emptyArrayInit[lendingPlatformIdIndex][index] += balance
}
})
})
console.log(emptyArrayInit,'emptyArrayInit');
/// [ [ 0, 0, 0, 500 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ] ]
it's simple to reach your goal.
const res=[] //to save result
platforms.map(platform=>{ //first loop
platform.bankAccounts.map(bank=>{ // inner loop bankaccounts
// to get lendingPlatforms
const lendPlatforms=platforms.find(p=>p.id==bank.lendingPlatformId);
//compare balance
if((lendPlatforms.bankAccounts[0].balance+bank.balance)==0)
res.push(true) // if combined balance is equal to zero
else
res.push(false)
})})
console.log(res)
In this array children array can have more childrens. I have a method in which I will get "lowValue" and "highValue". "Id" will be unique. when my method get called I need to use this unique id and replace old values of "lowValue" and "highValue" with the new ones. How can I do that?
// put your code here
<script>
myData = [{
"data": {
"name": "Applications",
"size": "200mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 1,
"name": "editor.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
}
},
{
"data": {
"id": 2,
"name": "settings.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
"mappedPersonaCount": 0,
}
}
]
},
{
"data": {
"name": "Cloud",
"size": "20mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 5,
"name": "backup-1.zip",
"highValue": 20,
"ratingID": 0,
"lowValue": 10
}
}]
}
]
</script>
Simple
const data = your_original_data
function replacer(lowValue, highValue, id){
for(let i = 0; i < data.length; i++){
for(let j = 0; j < data[i].children.length; j++){
if(data[i].children[j].data.id === id){
data[i].children[j].data.lowValue = lowValue
data[i].children[j].data.highValue = highValue
return
}
}
}
}
const myData = [{
"data": {
"name": "Applications",
"size": "200mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 1,
"name": "editor.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
}
},
{
"data": {
"id": 2,
"name": "settings.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
"mappedPersonaCount": 0,
}
}
]
},
{
"data": {
"name": "Cloud",
"size": "20mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 5,
"name": "backup-1.zip",
"highValue": 20,
"ratingID": 0,
"lowValue": 10
}
}]
}
]
const indexMap = new Map()
const parseDataToMap = (data = []) => {
data.forEach(e => {
if (e.children) {
e.children.forEach(e => {
indexMap.set(e.data.id, e.data)
})
}
})
}
parseDataToMap(myData)
console.log(myData[0].children[0].data)
const o = indexMap.get(1)
o.highValue = 25
o.lowValue = 11
console.log(myData[0].children[0].data)
Given the below-mentioned assumptions:
All children where id matches the supplied value will have the lowValue and highValue replaced.
The supplied id will always be present in the myData array in one or more children.
the following is one possible solution to achieve the desired result:
const replaceValues = (id = 5, lv = 5, hv = 50, arr = myData) => (
arr.reduce((f, i) => [...f, {
...i,
children: i.children.map(
child => ({
...child,
data: {
...child.data,
...(
child.data.id === id ? {
lowValue: lv,
highValue: hv
} : {}
)
}
})
)
}], [])
);
Explanation / Approach
The outer .reduce helps to iterate through the myData array
Each element in this array is placed as-is (using the ... spread operator)
Next, the children prop of each myData element is specified
Within this, i.children array is iterated using map to access each element
Each element here (again) is placed as-is using the ... spread-operator
Next, data is specified
Values for the data object are also spread (as before)
Then, if the data.id matches the parameter id then, lowValue and highValue are updated (using parameters lv and hv, respectively)
The ...( some_condition ? {k: v} : {} ) is one way to update an object's specific prop/s only when some_condition is true
Please use comments below to ask for further clarification/s.
Code Snippet
const myData = [{
"data": {
"name": "Applications",
"size": "200mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 1,
"name": "editor.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
}
},
{
"data": {
"id": 2,
"name": "settings.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
"mappedPersonaCount": 0,
}
}
]
},
{
"data": {
"name": "Cloud",
"size": "20mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 5,
"name": "backup-1.zip",
"highValue": 20,
"ratingID": 0,
"lowValue": 10
}
}]
}
];
const replaceValues = (id = 5, lv = 5, hv = 50, arr = myData) => arr.reduce((f, i) => [...f, {
...i,
children: i.children.map(
child => ({
...child,
data: {
...child.data,
...(
child.data.id === id ? {
lowValue: lv,
highValue: hv
} : {}
)
}
})
)
}], []);
console.log('replace id: 5, low: 5, high: 50', replaceValues());
console.log('replace id: 1, low: 11, high: 21', replaceValues(1, 11, 21));
I have a 2 nested object array, I would like to update the first array's nested array value with the second array nested array values. I had done a brute force approach but I would like to improve my logic.
The first array is
[{
"name": "data",
"values": [{
"cid": 1,
"ccount": 0
},
{
"cid": 2,
"ccount": 0
},
{
"cid": 3,
"ccount": 0
}
]
},
{
"name": "data1",
"values": [{
"cid": 1,
"ccount": 0
},
{
"cid": 2,
"ccount": 0
},
{
"cid": 3,
"ccount": 0
}
]
}
]
and the second array looks like
[{
"fName": "End",
"version": 1,
"cValues": [{
"id": 1,
"count": 2
},
{
"id": 2,
"count": 3
},
{
"id": 3,
"count": 4
}
]
},
{
"fName": "Start",
"version": 2,
"cValues": [{
"id": 1,
"count": 2
},
{
"id": 2,
"count": 12
},
{
"id": 3,
"count": 22
}
]
}
]
I would like to update the count of nested array values inside the first array based on the id of the second nested array values.
I had done a brute force approach, my code is
for (let i = 0; i < (arr1.length && arr2.length); i++) {
arr1[i].values[i].sort(this.sortByProperty("cid"));
for (let j = 0; j < (arr1[i].values[i].length && arr2[i].cValues.length); j++) {
if (arr1[i].values[j].cid == arr2[i].cValues[j].id) {
arr1[i].values[j].cCount = arr2[i].cValues[j].count;
}
}
}
sortByProperty(property) {
return function (a, b) {
if (a[property] > b[property])
return 1;
else if (a[property] < b[property])
return -1;
return 0;
}
}
Can anyone help me to improve my code logic?
How to get the array of objects based on condition in javascript.
I have array object obj in which each objects w1,w2...wn should have count greater than 2.
How to filter the array object based on object key in javascript.
function getObject (obj1){
var result = obj1.filter(e=> e.w1.count > 2 && e.w2.count > 2);
return result;
}
var output = this.getObject(obj1);
var obj1=[
{
"memberid": "s1",
"w1":{"count": 1, "qty": 1},
"w2":{"count": 0, "qty": 0},
... wn
"totalcount": 1
},
{
"memberid": "s2",
"w1":{"count": 2, "qty": 2, "amount": 400.0},
"w2":{"count": 1, "qty": 2, "amount": 503.0},
... wn
"totalcount": 5
},
{
"memberid": "s3",
"w1":{"count": 3, "qty": 2, "amount": 0.0},
"w2":{"count": 3, "qty": 4, "amount": 503.0},
... wn
"totalcount": 6
}
]
Expected Output:
[
{
"memberid": "s3",
"w1":{"count": 3, "qty": 2, "amount": 0.0},
"w2":{"count": 3, "qty": 4, "amount": 503.0},
... wn
"totalcount": 6
}
]
You can filter your array based on every value in each object either not being an object, or if it is an object, having a count greater than 2:
const obj1 = [{
"memberid": "s1",
"w1": {
"count": 1,
"qty": 1
},
"w2": {
"count": 0,
"qty": 0
},
"totalcount": 1
},
{
"memberid": "s2",
"w1": {
"count": 2,
"qty": 2,
"amount": 400.0
},
"w2": {
"count": 1,
"qty": 2,
"amount": 503.0
},
"totalcount": 5
},
{
"memberid": "s3",
"w1": {
"count": 3,
"qty": 2,
"amount": 0.0
},
"w2": {
"count": 3,
"qty": 4,
"amount": 503.0
},
"totalcount": 6
}
];
const out = obj1.filter(o => Object.values(o).every(v => typeof v != 'object' || v.count > 2));
console.log(out);
you need to iterate over the object keys, filtering out the invalid ones
function getObject(obj1) {
// filter
return obj1.filter(e =>
// based on the entries [key, value]
Object.entries(e)
// filter out entries where key is not a w followed by a number
.filter(val => val[0].match(/w\d+/))
// if every selected entry as a count > 2
.every(val => val[1].count > 2)
);
}
const obj1=[{memberid:"s1",w1:{count:1,qty:1},w2:{count:0,qty:0},totalcount:1},{memberid:"s2",w1:{count:2,qty:2,amount:400},w2:{count:1,qty:2,amount:503},totalcount:5},{memberid:"s3",w1:{count:3,qty:2,amount:0},w2:{count:3,qty:4,amount:503},totalcount:6}];
const output = this.getObject(obj1);
console.log(output)
docs of usefull functions :
Object.entries,
Array.filter,
Array.every
function getObject (obj1) {
var result = obj1.filter((e) => {
var isValid = false;
var i = 1;
while (e['w' + i]) {
if (e['w' + i].count > 2) {
isValid = true;
} else {
isValid = false;
break;
}
i++;
}
return isValid;
});
return result;
}
/*
Given an array of objects: ID|userName|totalScore|competitionRank,
number ID
string userName
number totalScore
number competitionRank
all competitionRanks are set to NULL
give each score a ranking in descending order
*/
I am currently not sure if this will pass all edge cases. Also, this seems to be the fastest I can do this, any help on improvements would be awesome. It passed for the test cases I could think of. Any help will be appreciated.
//Initialize data structure
var playerScores = [
{
"ID": 1,
"userName": "person1",
"totalScore": 230,
"competitionRank": null
},{
"ID": 2,
"userName": "person2",
"totalScore": 220,
"competitionRank": null
},{
"ID":3,
"userName": "person3",
"totalScore": 250,
"competitionRank": null
},{
"ID":4,
"userName": "person4",
"totalScore": 230,
"competitionRank": null
},{
"ID": 5,
"userName": "person5",
"totalScore": 250,
"competitionRank": null
}
];
playerScores.sort(function(a,b){
return b.totalScore - a.totalScore;
});
var numTies = 0;
playerScores[0].rank = 1;
for (i = 1; i < playerScores.length; i++){
if (playerScores[i].totalScore === playerScores[i-1].totalScore){
numTies++;
playerScores[i].rank = playerScores[i-1].rank;
}
else{
playerScores[i].rank = i+numTies;
numTies = 0;
}
}
console.log(playerScores);
I believe in your current code i + numTies should actually be i + numTies + 1, because the array indices (i) are zero-based but the ranks start at 1 (for the test data in the question this didn't cause a problem because the only non-tied item was last).
But you don't need the numTies variable at all because a non-tied element's rank will always be the same as its position within the array (+1).
Also, the line before your for loop that does the first item will give an error if the array is empty, so you should test for that. And use var to declare i:
var playerScores = [
{ "ID": 1, "userName": "person1", "totalScore": 230, "competitionRank": null },
{ "ID": 2, "userName": "person2", "totalScore": 220, "competitionRank": null },
{ "ID": 3, "userName": "person3", "totalScore": 250, "competitionRank": null },
{ "ID": 4, "userName": "person4", "totalScore": 230, "competitionRank": null },
{ "ID": 5, "userName": "person5", "totalScore": 250, "competitionRank": null }
];
playerScores.sort(function(a,b){ return b.totalScore - a.totalScore; });
if (playerScores[0]) playerScores[0].rank = 1;
for (var i = 1; i < playerScores.length; i++) {
if (playerScores[i].totalScore === playerScores[i-1].totalScore) {
playerScores[i].rank = playerScores[i-1].rank;
} else {
playerScores[i].rank = i + 1;
}
}
console.log(playerScores);
If you start the loop from 0 rather than 1, and test for the first element inside the loop, that gives you the option of restructuring the code to use an array iteration function rather than a for loop - which would be slower to execute but (arguably) easier to read.
For variety, I've used a ternary operator instead of an if/else:
var playerScores = [
{ "ID": 1, "userName": "person1", "totalScore": 230, "competitionRank": null },
{ "ID": 2, "userName": "person2", "totalScore": 220, "competitionRank": null },
{ "ID": 3, "userName": "person3", "totalScore": 250, "competitionRank": null },
{ "ID": 4, "userName": "person4", "totalScore": 230, "competitionRank": null },
{ "ID": 5, "userName": "person5", "totalScore": 250, "competitionRank": null }
];
playerScores.sort(function(a,b){ return b.totalScore - a.totalScore; });
playerScores.forEach(function(player, i, arr) {
player.rank = i === 0 || player.totalScore != arr[i-1].totalScore
? i + 1
: arr[i-1].rank;
});
console.log(playerScores);