I have an object that looks like this:
{
createdAt: "2016-01-25T04:01:53.282Z"
index: 0
objectId: "56a59e31a633bd0257868cb8"
panoDataRotate: 0
roomModelId: "56a59e242e958a00596a897c"
x: 240
y: 230
}
I want to clone it but into an object that only has index,x, andy`:
{
index: 0
x: 240
y: 230
}
How to do that with lodash/Underscore?
With lodash, you could use this:
var obj = {
createdAt: "2016-01-25T04:01:53.282Z",
index: 0,
objectId: "56a59e31a633bd0257868cb8",
panoDataRotate: 0,
roomModelId: "56a59e242e958a00596a897c",
x: 240,
y: 230
};
var newObject = _.pick(obj, ['index', 'x', 'y']);
See here the docs for _.pick() function.
And a plain JavaScript solution:
var obj = {
createdAt: "2016-01-25T04:01:53.282Z",
index: 0,
objectId: "56a59e31a633bd0257868cb8",
panoDataRotate: 0,
roomModelId: "56a59e242e958a00596a897c",
x: 240,
y: 230
};
var newObject = ['index', 'x', 'y'].reduce(function(result, key) {
result[key] = obj[key];
return result;
}, {});
for-in on data
You can use for-in to loop over properties of an object.
var data = {
createdAt: "2016-01-25T04:01:53.282Z",
index: 0,
objectId: "56a59e31a633bd0257868cb8",
panoDataRotate: 0,
roomModelId: "56a59e242e958a00596a897c",
x: 240,
y: 230
}
var allowedKeys = ["x", "y", "index"];
var result = {};
for (var key in data){
if(allowedKeys.indexOf(key)>-1){
result[key] = data[key];
}
}
console.log(result)
forEach over allowedKeys array
You can also loop over array of allowed keys to reduce code.
Note: In this approach, if key is not present in data, undefined will be assigned to it. But in prior approach, this key will be inserted.
For demo purpose, I have added a key test to allowedKeys array.
var data = {
createdAt: "2016-01-25T04:01:53.282Z",
index: 0,
objectId: "56a59e31a633bd0257868cb8",
panoDataRotate: 0,
roomModelId: "56a59e242e958a00596a897c",
x: 240,
y: 230
}
var allowedKeys = ["x", "y", "index", "test"];
var result = {};
allowedKeys.forEach(function(key){
result[key] = data[key];
})
console.log(result)
Related
im trying to normalize some data sitting in an array of objects.
[
{id: 1, number: 10, x: 0.3, y: 0.4, …}
{id: 2, number: 5, x: 0.5, y: 0.2, …}
{...}
{...}
{...}
]
I want to map the x and y entry's on a new value between 0 - 1250. So I get the following Array of Objects
[
{id: 1, number: 10, x: 375, y: 500, …}
{id: 2, number: 5, x: 625, y: 250, …}
{...}
{...}
{...}
]
Whats the best Practice for that?
Best,
Chris
You can use Array.map
const arr = [
{id: 1, number: 10, x: 0.3, y: 0.4},
{id: 2, number: 5, x: 0.5, y: 0.2}
];
// Use Array.map to iterate
const arr1 = arr.map(ob => {
ob.x*=1250;
ob.y*=1250;
return ob;
});
console.log(arr1);
Some thing like this with map method.
const arr = [
{id: 1, number: 10, x: 0.3, y: 0.4},
{id: 2, number: 5, x: 0.5, y: 0.2},
];
const res = arr.map(({x, y, ...rest}) => ({...rest, x: x * 1250, y: y * 1250 }));
console.log(res)
Assuming arr is your array of object. You can use map which returns new modified array.
let arr = [
{
id: 1, number: 10, x: 0.3, y: 0.4,
},
{
id: 2, number: 5, x: 0.5, y: 0.2
}
];
const normalize = (obj) => {
x = obj.x * 1250;
y = obj.y * 1250;
return {...obj, x, y};
// If you're only using mutating then
// above lines can be
// obj.x *= 1250;
// obj.y *= 1250;
// return obj;
}
// Not mutating array, output new array
const nonMutating = (arr) => {
let newRes = [];
arr.forEach(a => {
newRes.push(normalize(a));
});
return newRes;
}
console.log(nonMutating(arr));
console.log("\n");
// Mutating input array
const mutating = (arr) => {
return arr.map(a => normalize(a));
}
console.log(mutating(arr));
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);
I have an array that stores various objects. Looks like following:
[ 'key2': { id: 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2',
d: undefined,
x: 520,
y: 120 },
'Key1': { id: 'WA7WA2WAbWAdWAfWA9WA6WA8-WA7WAdWAeWA4-4WA4WA3WAb-WAaWAdWA4WAe-WA2WAbWAdWA5WA1WA0WA7WAbWA3WAdWAfWA9',
d: undefined,
x: 810,
y: 180 } ]
How do I push a value into the array such as:
['key3':{id:something, d:undefined,x:200,y:400}]
Here Key1, Key2, Key3 are all dynamically created and stored in a variable.
maybe You mean You have a literal like
var yourObj = { 'key1': ...
'key2': ...
}
and You want to push another one? if it's the case do it
yourObj[newKeyGenerated] = theNewObj;
You can have an array
var a = [{ id: 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2',
d: undefined,
x: 520,
y: 120 },
{ id: 'WA7WA2WAbWAdWAfWA9WA6WA8-WA7WAdWAeWA4-4WA4WA3WAb-WAaWAdWA4WAe-WA2WAbWAdWA5WA1WA0WA7WAbWA3WAdWAfWA9',
d: undefined,
x: 810,
y: 180 } ]
in this case a.push({...})
or an object
var a = { 'key2': { id: 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2',
d: undefined,
x: 520,
y: 120 },
'Key1': { id: 'WA7WA2WAbWAdWAfWA9WA6WA8-WA7WAdWAeWA4-4WA4WA3WAb-WAaWAdWA4WAe-WA2WAbWAdWA5WA1WA0WA7WAbWA3WAdWAfWA9',
d: undefined,
x: 810,
y: 180 } }
and then you can have a.key3 = {...}
If I have understood correctly , this should be the solution : https://jsfiddle.net/a7uxd4tk/
var data1 = [ {'key1': { id: 'a', d: undefined, x: 520, y: 120 }}];
var data2 = [ {'key2': { id: 'b', d: undefined, x: 520, y: 120 }}];
var data3 = [ {'key3': { id: 'b', d: undefined, x: 520, y: 120 }}];
var addData = [];
addData.push(data1[0]);
addData.push(data2[0]);
addData.push(data3[0]);
console.log(addData);
Also do note [ { and } ]
Try it:
var data = [ {'key2': { id: 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2',
d: undefined,
x: 520,
y: 120 }},
{'Key1': { id: 'WA7WA2WAbWAdWAfWA9WA6WA8-WA7WAdWAeWA4-4WA4WA3WAb-WAaWAdWA4WAe-WA2WAbWAdWA5WA1WA0WA7WAbWA3WAdWAfWA9',
d: undefined,
x: 810,
y: 180 }} ];
var newObj = {};
newObj.key3 = {};
newObj.key3.id = 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2';
newObj.key3.d = undefined;
newObj.key3.x = 520;
newObj.key3.y= 120;
data.push(newObj);
console.log(data);
I have an array like this.
var nodes = [{ID:"101", x:100, y:200}
,{ID:"102", x:200, y:200}
,{ID:"103", x:300, y:300}
,{ID:"104", x:200, y:300}];
I'd like to have a function which takes node's ID as input and return its (x,y).
For example, the function coordinates(103)should read the array (nodes) and return x = 300, y = 300 when it's called. Any pointer is appreciated. Thanks :)
This is what I have so far. It works but I'd like to know neater and tidier methods.
function coordinates(id){
for (var i=0 in nodes){
if(nodes[i].ID == id){
return { x: nodes[i].x, y: nodes[i].y};
}
}
}
console.log(coordinates(102));
basically you're looking at something like this
var f = function(id){
var match = nodes.filter(function(d){
return d.ID === id;
})
return match && match.length && {x: match[0].x, y:match[0].y}
|| {x: undefined, y: undefined};
};
then f('101') outputs {x: 100, y:200} and if cannot find a match then it will output {x: undefined, y: undefined}
You can use .filter, like so
var nodes = [{
ID: "101",
x: 100,
y: 200
}, {
ID: "102",
x: 200,
y: 200
}, {
ID: "103",
x: 300,
y: 300
}, {
ID: "104",
x: 200,
y: 300
}];
function coordinates(nodes, id) {
var result = nodes.filter(function (el) {
return +el.ID === id;
});
if (result && result.length) {
result = result[0];
return {
x: result.x,
y: result.y
};
}
return null;
}
console.log(coordinates(nodes, 103));
See comments inline:
Demo
var nodes = [{
ID: "101",
x: 100,
y: 200
}, {
ID: "102",
x: 200,
y: 200
}, {
ID: "103",
x: 300,
y: 300
}, {
ID: "104",
x: 200,
y: 300
}];
var noOfCord = nodes.length;
var coordinates = function(id) {
for (var i = 0; i < noOfCord; i++) {
if (nodes[i].ID == id) {
return {
x: nodes[i].x,
y: nodes[i].y
};
}
}
}
document.write(coordinates(103).x + ', ' + coordinates(103).y);
Using array filter, Try:
function coordinates(id){
return nodes.filter(function(e){ return e.ID == id })[0]
}
var nodes=[{ID:"101",x:100,y:200},{ID:"102",x:200,y:200},{ID:"103",x:300,y:300},{ID:"104",x:200,y:300}];
var result = coordinates("103");
document.write("<pre>" + JSON.stringify(result, null, 3));
Brilliant solutions with concrete JavaScript have already been proposed by people here. So I propose another alternative using underscore.js, just in case you're curious.
function coordinates(id){
var n = _.findWhere(nodes, {ID: id});
return {x: n.x, y: n.y }
}
I have asked this question before, but it seems the solution doesn't work well.
I have two objects:
var a = [{ x: 0, y: 0, color: "green", value: undefined, weight: 1 }, { x: 0, y: 1, color: "red", value: undefined, weight: 1 }];
var b = [{ x: 0, y: 0, value: 1}, { x: 0, y: 1, value: 3}];
I want to join them into a single object, like this:
var c = [{ x: 0, y: 0, color: "green", value: 1, weight: 1 }, { x: 0, y: 1, color: "red", value: 3, weight: 1 }];
Note: array A will always have 25 entries, while array b not.
The proposed solution was:
var extendedArray = $.extend({}, a, b);
However this makes an array of two entries, where not all values are preserved.
I have also tried the following functions:
var e = $.merge(a, b);
var output = a.concat(b);
function jsonConcat(o1, o2) {
for (var key in o2) {
o1[key] = o2[key];
}
return o1;
}
var c = {};
c = jsonConcat(c, a);
c = jsonConcat(c, b);
Any help or push in the right direction would be very much appreciated!
Edited to reflect that b can be smaller but never larger than a.
function merge(a,b){
//Don't want to mutate a
var result = a.slice();
for(var i = 0; i < b.length; i++){
for (var attrname in b[i]) {
result[i][attrname] = b[i][attrname];
}
}
return result;
}
Code partly taken from accepted answer in: How can I merge properties of two JavaScript objects dynamically?
Assuming that the two arrays have the same length, an in place merge could be something like this:
var a = [{ x: 0, y: 0, color: "green", value: undefined, weight: 1 }, { x: 0, y: 1, color: "red", value: undefined, weight: 1 }];
var b = [{ x: 0, y: 0, value: 1, weight: 1 }, { x: 0, y: 1, value: 3, weight: 1 }];
function merge_objects(o1, o2) {
Object.keys(o2).forEach(
function(key) {
o1[key] = o2[key];
});
}
function merge(a, b) {
if (a.length != b.length) {
throw new Error();
}
for (var ix=0; ix<a.length; ix++) {
merge_objects(a[ix], b[ix]);
}
}
$.extend without the first argument set to true will only merge the "first level" of your objects. It works if your properties are only strings and numbers, but if some properties are objects, it can result in unexpected behaviour.
I think you're looking for $.extend(true,obj1,obj2) .
example
var a = [{ x: 0, y: 0, color: "green", value: undefined, weight: 1 }, { x: 0, y: 1, color: "red", value: undefined, weight: 1 }];
var b = [{ x: 0, y: 0, value: 1, weight: 1 }, { x: 0, y: 1, value: 3, weight: 1 }];
var c = $.extend(true,[],a,b);
console.log(c instanceof Array); // true
see the doc for details
the first argument true tells the method to perform a "deep" copy, recursively.