Clone javascript object and update the values - javascript

I have a problem with the logic to update the values in a json.
Initial json is
var val = {
"data": [
{x: 1396328400000, y: 92, num: "243"},
{x: 1425189600000, y: 91, num: "158"}
]
};
I want to duplicate data into another object data1 containing this in val.
Considering current month is March 2015, timeInMilliSeconds will give the value as 1425189600000, If the code encounters this value, it should replace the num in first data array to 0. Except the 1425189600000 in data1 all the values should be 0
Here is the jsfiddle
var date = new Date();
timeInMilliSeconds = Date.parse(date.getFullYear() + "/" +(date.getMonth()+1));
val = {
"data": [
{x: 1396328400000, y: 92, num: "243"},
{x: 1425189600000, y: 91, num: "0"}
],
"data1": [
{x: 1396328400000, y: 92, num: "0"},
{x: 1425189600000, y: 91, num: "158"}
]
};

Looks to me like you just need to update your check to make sure you're casting to a number:
if(k == 'num' && parseInt(val.data[prop]['x']) == timeInMilliSeconds) {

Related

How to apply custom formatting for a JSON stringify?

I have the following code:
const sample = [
{
name: "apple",
points: [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 7, y: 8 } ],
age: 24
},
{
name: "banana",
points: [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 7, y: 8 } ],
age: 45
}
];
const qwer = JSON.stringify(sample, null, 2);
console.log(qwer);
If you run it, you'll notice it has nice formatting, except for the points array, which is extremely verbose.
I would like everything to be indented like normally (which is why I'm passing in 2 for the final parameter to stringify), but I would like the points array to only take a single line, like how it is declared in the code.
The reason for this is because currently each points array is stretched to like 18 lines, when there will only ever be 3 or 4 items. I would like them to stay on one line.
I tried to use a custom replacer, and while it somewhat worked, it forced the JSON array to be a string. But it's not a string. I want it to stay an array.
Is there any way to do this?
For the general solution, a mini parser would be the best approach, but a quick but ugly-looking approach would be to use a replacer to replace arrays with stringified strings with a unique value as a prefix which can be replaced afterwards.
const sample = [
{
name: "apple",
age: 24,
points: [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 7, y: 8 } ],
},
{
name: "banana",
age: 45,
points: [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 7, y: 8 } ],
}
];
const withNestedStringifiedArrays = JSON.stringify(
sample,
(key, value) => key && Array.isArray(value) ? '##UNIQUE##' + JSON.stringify(value) : value,
2
);
const output = withNestedStringifiedArrays.replace(
/"##UNIQUE##(.*?)"(,)?$/gm,
(_, stringifiedArr, possibleComma = '') => stringifiedArr.replaceAll('\\', '') + possibleComma
);
console.log(output);

Merge objects in array with similar key

I have an array of objects:
objArray = [
{x: 1, y: 7},
{x: 2, y: 14},
{x: 1, z: 9},
{x: 2, z: 18}
{x: 1, n: 6}
{x: 2, n: 16}
]
Is there an efficient way to merge for "X" without a for loop? so that I end up with:
objArray = [
{x: 1, y: 7, z: 9, n: 6},
{x: 2, y: 14, z: 18, n: 16}
]
So look for common objArray[n]["x"] and merge all hits into one object? It's OK to modify the original array or create a new one.
I'm aware this can be done with a loop, but I'm trying to avoid too many loops for this implementation, though I'm not sure if a reduce or a filter would work for this.
You could take a Map and group by property x.
var array = [{ x: 1, y: 7 }, { x: 2, y: 14 }, { x: 1, z: 9 }, { x: 2, z: 18 }, { x: 1, n: 6 }, { x: 2, n: 16 }],
result = Array.from(
array
.reduce((m, o) => m.set(o.x, Object.assign({}, m.get(o.x), o)), new Map)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use reduce method to build an object and then Object.values to get an array.
const data = [{"x":1,"y":7},{"x":2,"y":14},{"x":1,"z":9},{"x":2,"z":18},{"x":1,"n":6},{"x":2,"n":16}]
const res = data.reduce((r, {x, ...rest}) => {
if(!r[x]) r[x] = {x, ...rest}
else Object.assign(r[x], rest);
return r;
}, {})
const result = Object.values(res);
console.log(result)
You can do it with Array#reduce:
const objArray = [
{x: 1, y: 7},
{x: 2, y: 14},
{x: 1, z: 9},
{x: 2, z: 18},
{x: 1, n: 6},
{x: 2, n: 16},
]
const result = Object.values( objArray.reduce(
(p,c) => (p[c.x] = Object.assign( {}, p[c.x], c ), p ), {}
) );
console.log( result );

How to push an object into an object?

So i have a object like this:
let obj = {'0': {x: 25, y: 12}, '1': {x:55, y:6} ,...}
Now How can I push an other object like {x: 12, y: 15} in to this object?
Insert your data in the last index (you can get the last index converting the object to array and getting the length)
let obj = {'0': {x: 25, y: 12}, '1': {x:55, y:6}}
obj[Object.values(obj).length] = {x: 12, y: 15}
console.log(obj)

Comparing JavaScript objects

0
:
{a: "5", b: "gg", X: "dd", Y: "dd", Z: "dd"}
1
:
{X: "dd", Y: "dd", Z: "dd"}
2
:
{X: "df", Y: "dd", Z: "dd"}
I want to compare these objects with each other so that i can not add repeated object in an array.
If I understand your question with given information, there can be 2 possible scenarios.
if you want to add one object to another object (merge) based on key than it can be done with angular.extend and the same key will be overwritten by later object keys
let inp1 = {a: "aa", b: "bb", X: "xx", Y: "yy", Z: "zz"};
let inp2 = {X: "xxx", Y: "yyy", Z: "zzz", W: "www"};
let inp3 = {X: "x3", Y: "y3", Z: "z3"};
angular.extend(inp1, inp2);
console.log("inp1", inp1);
// print {"a": "aa", "b": "bb", "X": "xxx","Y": "yyy","Z": "zzz","W": "www"}
if you simply want to compare two objects before adding into another object or (push into array) then you can do it with angular.equals
anguar.equals(inp2,inp3) // return false

d3 filter duplicates names from csv

with d3.csv I am reading a csv that is then stored such that
console.log(data[0]) returns
Object {username: "mark", y: 0, x: 0, value: 0}
Now I want to extract from data only the first occurence of each username.
In python pandas I would have used data.drop_duplicates(columns='username')
EDIT:
Consider the following example:
var X = [{username: "a", y: 0, x: 0, value: 0},
{username: "b", y: 0, x: 0, value: 0},
{username: "a", y: 1, x: 0, value: 0}
{username: "c", y: 0, x: 0, value: 0}
{username: "b", y: 1, x: 0, value: 0}]
it should return only:
var Y = [{username: "a", y: 0, x: 0, value: 0},
{username: "b", y: 0, x: 0, value: 0},
{username: "c", y: 0, x: 0, value: 0}
i.e. f(X) = Y
Since you want to find the first occurrence of each username, this question has nothing to do with D3, and can be solved with plain JavaScript.
There are several ways for doing this. A simple one is using Array.prototype.find():
The find() method returns the value of the first element in the array that satisfies the provided testing function. (emphasis mine)
Here is a demo. First, we get the unique values for usernames as an array:
var users = [...new Set(data.map(function(d) {
return d.username
}))];
Then, we use a map with filter to get the first occurences:
var firstOccurrence = users.map(function(d) {
return data.find(function(e) {
return e.username === d
})
});
Check the demo:
var data = [{
username: "a",
y: 0,
x: 0,
value: 0
}, {
username: "b",
y: 0,
x: 0,
value: 0
}, {
username: "a",
y: 1,
x: 0,
value: 0
}, {
username: "c",
y: 0,
x: 0,
value: 0
}, {
username: "b",
y: 1,
x: 0,
value: 0
}];
var users = [...new Set(data.map(function(d) {
return d.username
}))]
var firstOccurrence = users.map(function(d) {
return data.find(function(e) {
return e.username === d
})
});
console.log(firstOccurrence)
You can employ a Map to keep track of what usernames have already been processed. Using the username as the key ensures the uniqueness of this value. To get the first occurence of this value instead of the last one, you further have to use Map.prototype.has() to check if each particular value has already been added.
var X = [
{username: "a", y: 0, x: 0, value: 0},
{username: "b", y: 0, x: 0, value: 0},
{username: "a", y: 1, x: 0, value: 0},
{username: "c", y: 0, x: 0, value: 0},
{username: "b", y: 1, x: 0, value: 0}
];
var uniqX = new Map(); // Construct map of unique usernames
X.forEach(x => {
if (!uniqX.has(x.username)) uniqX.set(x.username, x); // Only add, if not present
});
var Y = uniqX.values(); // Retrieve the result set
console.log(...Y);
Or, rewritten for the sake of mathematical aesthetics:
var X = [
{username: "a", y: 0, x: 0, value: 0},
{username: "b", y: 0, x: 0, value: 0},
{username: "a", y: 1, x: 0, value: 0},
{username: "c", y: 0, x: 0, value: 0},
{username: "b", y: 1, x: 0, value: 0}
];
function f(_) {
let uniqX = new Set();
return _.filter(({username}) => !uniqX.has(username) && uniqX.add(username));
}
var Y = f(X);
console.log(...Y);

Categories