What is the best way to create new object from existing object with certain values, I mean i have one onbject and i want to create a new one with only the values that i need;
For example;
Existing object
data = [{
"ID": "234324234",
"calldate": "2018-03-25",
"callend": "2018-03-25",
"duration": "00:32",
"connect_duration": "00:01",
"progress_time": "2",
"first_rtp_time": "2",
"caller": "3243242342",
"caller_domain": "XXX.XXXX.XXX",
}, {
"ID": "5675675",
"calldate": "2018-03-12",
"callend": "2018-03-12",
"duration": "00:45",
"connect_duration": "00:04",
"progress_time": "2",
"first_rtp_time": "2",
"caller": "878678865",
"caller_domain": "XXX.XXXX.XXX",
}]
new Object required;
new_object = [{
"ID": "234324234",
"calldate": "2018-03-25",
"callend": "2018-03-25",
"caller": "3243242342",
}, {
"ID": "5675675",
"calldate": "2018-03-12",
"callend": "2018-03-12",
"caller": "878678865",
}]
you can do something like that by using map function
const new_object = data.map(({ ID, calldate, callend, caller }) => {
return { ID, calldate, callend, caller };
});
You can use class-transformer.
Create a class with all the properties you need
Convert plain (literal) objects to class (constructor) objects with proper options.
You can also look at the implementation of plainToClass and implement your own.
Related
I have this object:
var ages = [{
"getasafieldDetail": {
"id": "xxx",
"asaentrySet": [{
"result": "ON",
"buy": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "2001-08-09 at 11:52 pm",
"value": 5.0
}]
}]
}
}];
and i want to add an element and have an output like this:
var ages = [{
"getasafieldDetail": {
"id": "xxx",
"asaentrySet": [{
"result": "ON",
"buy": {
"username": "Dis"
},
"land": "111", // THIS <<<<------------
"offerSet": [{
"createdStr": "2001-08-09 at 11:52 pm",
"value": 5.0
}]
}]
}
}];
i tried using splice but not works...
ages.splice(ages[0]['getasafieldDetail']['asaentrySet'][0]['offerSet'],0,'"land": "111"');
ages.join();
There is the handy syntax of Destructuring assignments which helps with cutting and reassembling objects.
Edit
#FireFuro99 did point to the ES6/ES2015 spec which explicitly states how to preserve/handle an object's key-order at the object's creation time.
Thus one can say ...
Every JS engine which does support Destructuring assignment has to respect too any object's key order from/at this object's creation time.
const ages = [{
getasafieldDetail: {
id: "xxx",
asaentrySet: [{
result: "ON",
buy: {
username: "Dis",
},
offerSet: [{
createdStr: "2001-08-09 at 11:52 pm",
value: 5.0,
}],
}],
},
}];
const { result, buy, ...rest } = ages[0].getasafieldDetail.asaentrySet[0];
ages[0].getasafieldDetail.asaentrySet[0] = {
result,
buy,
land: "111",
...rest,
};
console.log({ ages });
.as-console-wrapper { min-height: 100%!important; top: 0; }
Splice only works on Arrays.
To make this work, convert your Object to an Array using Object.entries(), then use splice, and then convert it back to an object using Object.fromEntries().
const entrySet = Object.entries(ages[0]['getasafieldDetail']['asaentrySet'][0]);
entrySet.splice(2,0, ["land", "111"]);
ages[0]['getasafieldDetail']['asaentrySet'][0] = Object.fromEntries(entrySet);
This will insert the key-value pair at the the specified position.
The advantage this has over the destructuring assignment is, that you can specify the index, whereas destructuring is pretty hardcoded.
ages[0]["getasafieldDetail"]["asaentrySet"][0].land = '111' will create the key land in the first object in asaentrySet and assign the value 111. Key order is not guaranteed
var ages = [{
"getasafieldDetail": {
"id": "xxx",
"asaentrySet": [{
"result": "ON",
"buy": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "2001-08-09 at 11:52 pm",
"value": 5.0
}]
}]
}
}];
ages[0]["getasafieldDetail"]["asaentrySet"][0].land = '111'
console.log(ages)
When it is an array of objects you could simple, add, passing the position that you want by editing the array like the example below:
let land = {land: 1111}
let ages = [{'a':11},'2', 'wd']
let new =[]
new.push(ages[1])
new.push(land)
ages[1] = new
console.log(ages)
output:
(3) [{…}, Array(2), "wd"]
You get what you want from the array, edit it, and put back in the same position, may it can help.
I've been trying to wrap my head around filtering arrays of objects for a while now, but I can't seem to really get a hang on it. Although I usually have working code in the end, it just doesn't look like elegant code to me. So, I'd appreciate a code review and some hints very much!
Example:
I'm currently working on this example for an online shop where I need to retrieve product details out of an array of objects based on an id.
This is my helper function:
function getItemDetails(id) {
var getCategory = shelf.filter(obj => obj.articleList.some(cat => cat.id === id));
var getArticleList = getCategory[0].articleList;
var getItem = getArticleList.filter(item => item.id == id);
return getItem
}
Steps: In a first step, I tried to filter the shelf array, but it would return the entire array articleList of the corresponding item.
So, I filtered the result again with the same criteria and it works, but it just looks awfully redundant to me.
This is an example of the data:
const shelf = [{
"categoryPrice": "2",
"categoryTitle": "Flyer",
"articleList": [{
"id": "1",
"articleTitle": "Green",
}, {
"id": "2",
"articleTitle": "Blue",
}],
}, {
"categoryPrice": "3",
"categoryTitle": "Post card",
"articleList": [{
"id": "3",
"articleTitle": "Purple"
}, {
"id": "4",
"articleTitle": "Yellow",
}]
}]
I checked various questions here, including:
Vue/Javascript filter in deep object inside object array
Deep filter objects in javascript array
But none of them provide an easier, more concise solution, in my opinion. What am I missing?
Thanks for your help!
This might be a better fit for codereview but if the question is just 'How to make this more concise' I would suggest something like following:
const shelf = [{
"categoryPrice": "2",
"categoryTitle": "Flyer",
"articleList": [{
"id": "1",
"articleTitle": "Green",
}, {
"id": "2",
"articleTitle": "Blue",
}],
}, {
"categoryPrice": "3",
"categoryTitle": "Post card",
"articleList": [{
"id": "3",
"articleTitle": "Purple"
}, {
"id": "4",
"articleTitle": "Yellow",
}]
}]
const findItem = function(shelves, id) {
return shelves.flatMap((shelf) => shelf.articleList).find((article) => article.id == id) || null;
}
console.log(findItem(shelf, 1));
console.log(findItem(shelf, 3));
The above example concatenate all the list of articles and then searches that array for the article with the supplied ID.
Performance wise? Not the best, but you asked for something concise and this is about as concise as one can hope for with the given data structure.
This code is O(1), which means that lookup per article.id is constant. It will however use more memory. To conserve memory, I used WeakMap, as long as you use the same shelf variable, it will not recompute it. But once you replace it, it will also perish from the cache.
const shelf = [{
"categoryPrice": "2",
"categoryTitle": "Flyer",
"articleList": [{
"id": "1",
"articleTitle": "Green",
}, {
"id": "2",
"articleTitle": "Blue",
}, {
"id": "3", // Added
"articleTitle": "Violet",
}],
}, {
"categoryPrice": "3",
"categoryTitle": "Post card",
"articleList": [{
"id": "3",
"articleTitle": "Purple"
}, {
"id": "4",
"articleTitle": "Yellow",
}],
}];
const findItems = function(shelves, id) {
if (!findItems._map) {
// Create computation cache holder
// Weak map will make sure, that if the object is disposed, it can be garbage collected, with it will be gone its cache too! (That is awsome!)
findItems._map = new WeakMap();
}
if (!findItems._map.has(shelves)) {
// For every shelves object, we will create a new Map containing all mapped values.
const map = new Map();
findItems._map.set(shelves, map);
shelves.forEach(shelf => {
shelf.articleList.forEach(article => {
if (!map.has(article.id)) {
// If list is not yet created create it with the article
return map.set(article.id, [ article ]);
}
// If it exists, add to it
map.get(article.id).push(article);
});
});
}
return findItems._map.get(shelves).get(id);
}
console.log(findItems(shelf, "1"));
console.log(findItems(shelf, "3"));
You can get away with looping twice. Once for the outer array and once for the articleList array
const findItem = (id) =>
shelf.reduce((acc, current) => {
const found = current.articleList.find((x) => x.id === id);
if (found) return [...acc, found];
return acc;
}, []);
I have an array and I need to order the data of it by the distance of a specific point.
Knowing that .sort() won't work since I'm dealing with coordinates, I've been using a library called Geolib which has a function called getPreciseLocation() which is exactly what I need, but it doesn't seem to work while iterating through an array.
Here is the array containing the data I will be using.
Data:
[
{
"id": "1",
"Point": "27.1597268, 40.6646601"
},
{
"id": "2",
"Point": "11.1640393, 49.648713"
},
{
"id": "3",
"Point": "26.1539253, 42.6599287"
},
{
"id": "4",
"Point": "21.1597268, 44.6646601"
},
{
"id": "5",
"Point": "10.1640393, 43.648713"
},
{
"id": "6",
"Point": "26.1539253, 61.6599287"
}
]
The code I've been trying to use to iterate through the array.
let DistancesFromUserLocation = [];
this.state.Data.forEach(item => {
DistancesFromUserLocation.push(geolib.getPreciseDistance({latitude: 30.1891168, longitude: 11.6226982}, item.Point))
})
As a disclaimer: I only need to get to receive the distance of each array object to a new array.
I've tried and researched many things and get around the solution, but just about thinking that I am getting to the solution, something would go wrong.
You need to push the generated distance each iteration to DistancesFromUserLocation array.
let DistancesFromUserLocation = [];
this.state.Data.forEach(item => {
// push each distance to `DistancesFromUserLocation`
DistancesFromUserLocation.push(
geolib.getPreciseDistance(
{latitude: 30.1891168, longitude: 11.6226982},
item.Point
);
)
})
Only then you can use the Array.sort().
console.log(DistancesFromUserLocation.sort());
EDIT:
Check my working example here at codesandbox.
How can I get the new object added to an array after componentDidUpdate?
I have this two objects in prevProps:
objArray1 = [
{
"id": 1,
"name": "abc",
},
{
"id": 2,
"name": "def",
}
]
and I get this three objects in this.props
objArray2 = [
{
"id": 1,
"name": "abc",
},
{
"id": 2,
"name": "def",
},
{
"id": 3,
"name": "ghi",
}
]
and I want to get at the object that changed
newObject ={
"id": 3,
"name": "ghi",
}
so that I can pass it to another function
Create a Set of id values from the prevProps with Array.map(), and filter out the new props that has an id that exists in the Set:
const prevProps = [{"id":1,"name":"abc"},{"id":2,"name":"def"}]
const props = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"ghi"}]
const prevSet = new Set(prevProps.map(o => o.id))
const added = props.filter(o => !prevSet.has(o.id))
console.log(added)
If new items are always added to the end of the array, you can use Array.slice() to remove the previous items (the length of `prevProps), and get the new items:
const prevProps = [{"id":1,"name":"abc"},{"id":2,"name":"def"}]
const props = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"ghi"}]
const added = props.slice(prevProps.length)
console.log(added)
You can filter objArray2 with id
objArray2.filter(ele=> !objArray1.some(value=> value.id === ele.id) )
If extra items are always added after the previous object you can slice
objArray2.slice(objArray1.length,)
if the IDs increment by one each time they're added. Then you could store the latest id and check for greater ones on update.
This one is a tricky one.
So, lets say I have two JS objects that are fetched via REST call, via two callbacks.
So, we have:
call1() - POST method - parsed JSON to JS object, route: {{url}}/data
call1.json:
"data": [
{
"id": "1",
"volume:" "2000"
},
{
"id": "2",
"volume:" "3000"
},
{
"id": "3",
"volume:" "4000"
},
{
"id": "4",
"volume:" "5000"
}
];
call2(req.body.id) - GET method - parsed JSON to JS object, route: {{url}}/data/:id
For example, if I pass req.body.id as = 1 got from the first response, it will open data for that id. So:
return call2(2) will return the data from this JSON: call2.json:
"data": [
{
"id": "1",
"add_data": "important string",
"add_data_2": "important string two"
},
];
The bottom line is, when doing the {{url}}/data route call - call() I need to serve all the data from {{url}}/data/:id routes, and bind them to the correct id. So, for example, the scenario I am trying to achieve is this:
Inside call(): get call1.json: data, do as many call2(req.body.id) calls as there are ids in the first object and then combine add_data and add_data_two values in the first object. So for example the final object would look like this.
console.log(response)
"data": [
{
"id": "1",
"volume:" "2000",
"add_data": "important string",
"add_data_2": "important string two"
},
{
"id": "2",
"volume:" "3000",
"add_data": "important string",
"add_data_2": "important string two"
},
{
"id": "3",
"volume:" "4000",
"add_data": "important string",
"add_data_2": "important string two"
},
{
"id": "4",
"volume:" "5000",
"add_data": "important string",
"add_data_2": "important string two"
}
];
This is what I have tried so far:
async get_data(req) {
try {
const objFirst = await call1(); //gets data
let objTwo = '';
for (let i = 0; i < objFirst.data.length; i++) {
objTwo = await call2({id: objFirst.data[i].id}) //gets data
}
return objFirst;
} catch(err) {
console.log("Error: ", err)
}
}
But it does not work. How can I get all data, and make as many as call2(id) as there are ids and combine that all in one object? Basically, I need to repeat this callback -> call2(id) as many ids we receive in call1().
Thanks, sorry if it looks like a mess.
You can use the map function and spread operator for this. Something like below.
Call2 function just simulates what an endpoint would return, but you get the idea.
var data = [
{
id: 1,
add_data: "1111"
},
{
id: 2,
add_data: "2222"
}
];
var data2 = [
{
id: 1,
volume: "bla"
},
{
id: 2,
volume: "bla"
}
];
function call2(id) {
return data2.filter(x => x.id == id)[0];
}
var result = data.map(x => {
var response = call2(x.id);
return {
...x,
...response
}
})
console.dir(result[0]);
The speed of your solution (loop through an array and doing http calls to get more data is really slow). If you have a lot of these functions that needs to combine data from different datasources, and depending on your project size, i would look into either RXJS or GraphQL (If you really need performance). RXJS have great functions to merge, combine, map etc data.
RXJS
GraphQL