This question already has answers here:
Self-references in object literals / initializers
(30 answers)
Closed 6 years ago.
I have an object like this...
"data": {
"1": {
"id": 32,
"name": "E",
"link": "",
},
"2": {
"id": 33,
"name": "EC",
"link": "",
},
}
how can I set each "link" value using the vars above ? for example I would like to do some thing like
"data": {
"1": {
"id": 32,
"name": "E",
"link": "id="+this.id+" and name="+this.name,
},
"2": {
"id": 33,
"name": "EC",
"link": "id="+this.id+" and name="+this.name,
},
To make the object like this...
"data": {
"1": {
"id": 32,
"name": "E",
"link": "id=32 and name=E",
},
"2": {
"id": 33,
"name": "EC",
"link": "id=33 and name=EC",
},
I suggest to iterate over the properties and change the wanted items.
var object = { data: { "1": { "id": 32, "name": "E", "link": "", }, "2": { "id": 33, "name": "EC", "link": "", } } };
Object.keys(object.data).forEach(function (k) {
object.data[k].link = 'id=' + object.data[k].id + ' and name=' + object.data[k].name;
});
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');
I typically make it a function:
"data": {
"1": {
"id": 32,
"name": "E",
"get_link": function() { return "id="+this.id+" and name="+this.name }
}
}
Then you access it like whatever.get_link()
There are two ways to go about solving this.
You can create a post-processor to process placeholder values. I made a generic pre-processor which should dynamically search for placeholders for all string properties.
var linkStore = {
"data": {
"1": {
"id": 32,
"name": "E",
"link": "id={{id}} and name={{name}}"
},
"2": {
"id": 33,
"name": "EC",
"link": "id={{id}} and name={{name}}"
}
}
};
function postProcess(data, root) {
var records = root != null ? data[root] : data;
Object.keys(records).forEach(function(recordId) {
var record = records[recordId];
Object.keys(record).forEach(function(property) {
if (typeof record[property] === 'string') {
record[property] = record[property].replace(/{{(\w+)}}/g, function(match, value) {
return record[value];
});
}
});
});
return data;
}
var result = postProcess(linkStore, 'data');
document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 2) + '</pre>';
Or if you don't want to modify the original data. You can add a property map to be applied to each of the records.
var linkStore = {
"data": {
"1": {
"id": 32,
"name": "E",
"link": ""
},
"2": {
"id": 33,
"name": "EC",
"link": ""
}
}
};
function postProcess(data, root, propertyMap) {
var records = root != null ? data[root] : data;
Object.keys(records).forEach(function(recordId) {
var record = records[recordId];
Object.keys(propertyMap).forEach(function(property) {
record[property] = propertyMap[property].call(record, record[property]);
});
});
return data;
}
var result = postProcess(linkStore, 'data', {
link : function(oldValue) {
return 'id=' + this.id + ' and name=' + this.name
}
});
document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 2) + '</pre>';
Related
How to combine JSON objects in the same response that has the same key and value with javascript? This is my data for example:
{
"data": [
{
"name": "A",
"description": {
"location": "location1",
"floor": "floor1",
},
},
{
"name": "A",
"description": {
"location": "location2",
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
}
And turn it into this:
{
"data": [
{
"name": "A",
"description": {
"location": ["location1","location2"],
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
}
Basically I am someone who is new to learning javascript. Any help would be very helpful, thank you.
You can do:
const data = {data: [{name: 'A',description: {location: 'location1',floor: 'floor1',},},{name: 'A',description: {location: 'location2',floor: 'floor1',},},{name: 'B',description: {location: 'location3',floor: 'floor3',},},],}
const result = {
data: data.data.reduce((a, { name, description }) => {
const index = a.findIndex((d) => d.name === name)
if (index >= 0) {
let location = a[index].description.location
location = Array.isArray(location) ? location : [location]
a[index].description.location = [...location, description.location]
} else {
a.push({ name, description })
}
return a
}, []),
}
console.log(result)
const list = {
"data": [
{
"name": "A",
"description": {
"location": "location1",
"floor": "floor1",
},
},
{
"name": "A",
"description": {
"location": "location2",
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
};
const consolidatedData = [];
for (const ele of list.data) {
const isExist = consolidatedData.find(x => x.name === ele.name);
if (!isExist) {
consolidatedData.push({
...ele
})
} else {
const objectKey = consolidatedData.findIndex(x => x.name === ele.name);
if (objectKey > -1) {
const description = consolidatedData[objectKey].description;
const newDes = ele.description;
if (newDes.location !== description.location) {
const data = consolidatedData[objectKey].description;
const added = [data.location, ele.description.location];
delete consolidatedData[objectKey].description.location
consolidatedData[objectKey].description["location"] = added
}
if (newDes.floor !== description.floor){
const data = consolidatedData[objectKey].floor;
const added = [data.floor, ele.description.floor];
delete consolidatedData[objectKey].description.floor
consolidatedData[objectKey].description["floor"] = added
}
}
}
}
console.log(JSON.stringify(consolidatedData, null, 2));
Here is a solution that uses an intermediate bucket object. The desired result object is then constructed from the bucket object:
const input = { "data": [ { "name": "A", "description": { "location": "location1", "floor": "floor1", }, }, { "name": "A", "description": { "location": "location2", "floor": "floor1", }, }, { "name": "B", "description": { "location": "location3", "floor": "floor3", }, }, ] };
let buckets = input.data.reduce((acc, obj) => {
if(!acc[obj.name]) {
acc[obj.name] = {
locations: {},
floors: {}
};
}
acc[obj.name].locations[obj.description.location] = true;
acc[obj.name].floors[obj.description.floor] = true;
return acc;
}, {});
console.log('buckets: ', buckets);
let result = {
data: Object.keys(buckets).map(name => {
let locations = Object.keys(buckets[name].locations);
let floors = Object.keys(buckets[name].floors);
return {
name: name,
description: {
location: locations.length == 1 ? locations[0] : locations,
floor: floors.length == 1 ? floors[0] : floors
}
}
})
};
console.log('result:', result);
Notes:
buckets object:
is created using an array .reduce()
array .reduce() docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
locations and floors are collected using objects instead of arrays, this is to avoid duplicate names
result object:
is using Object.keys(buckets) to get the array of names
.map() transforms each name into the desired object
your unusual array or string value for location and floor is constructed with a conditional
I have an object that has a whole host of arrays and properties. There is a property called targetProperty which appears in various places of the object.
I have a function where if the user clicks yes, every instance of that property needs to be reassigned to a new value.
The problem is the function that I used for assigning a new value doesn't work in this senario:
reassingPropertyInObj(obj, status) {
if (typeof obj === 'object' && obj !== null) {
obj.targetProperty = status;
for (const key in obj) {
this.handleExpandCollapseClick(obj[key], status);
}
}
},
Does anyone have a solution for this? Also can't use JSON.parse() or anything like that because the properties need to stay reactive for later reassignment if needed by the user.
Below is an example of one object:
{
"id": 16,
"ref_study_id": "3412333",
"title": "SomePersonNameOne",
"capabilities_available": [
{
"id": 75,
"name": "Clinical Data",
},
{
"id": 538,
"name": "RK's Capability",
}
],
"capabilities_impacted": [],
"businessImpact": {
"id": 2,
"name": "Medium"
},
"sites_impacted": [],
"sites_available": []
},
{
"id": 6,
"ref_study_id": "123124",
"title": null,
"capabilities_available": [
{
"id": 37,
"name": "Clinical Site Experience,
},
{
"id": 41,
"name": "Experience",
}
],
"capabilities_impacted": [
{
"id": 37,
"name": "Information Exchange",
"is_study_level": false,
"businessImpact": {
"id": 2,
"name": "Medium"
}
},
{
"id": 39,
"name": "IT/Data Experience",
"is_study_level": false,
"businessImpact": {
"id": 2,
"name": "Medium"
}
},
{
"id": 34,
"name": "Mgmt & Storage",
"is_study_level": false,
"businessImpact": {
"id": 3,
"name": "Minor"
}
}
],
"businessImpact": {
"id": 2,
"name": "Medium"
},
"sites_impacted": [],
"sites_available": []
},
And the property in question is businessImpact. As you can see it appears by itself as a property and inside array (and sometimes those arrays of arrays of their own).
I setup a function like:
arrayOfProperties.forEach((property) => {
obj[property].forEach((o) => {
o.businessImpact = newVal;
});
});
But of course it doesn't go deep enough.
I am trying to develop a dynamic DraggableFlatList with react native redux, where the updated array from onDragEnd is dispatched to the store. Hence I am trying to create a function where I use the "from" and "to" parameters from the return object from onDragEnd to alter a new array before dispatch. As an example, in the object below, I work with three items, that are objects from the array:
Object {
"data": Array [
Object {
"backgroundColor": "rgb(154, 0, 132)",
"category": "Practical",
"description": "Zero",
"duedate": Object {
"cond": false,
"date": "",
},
"id": 0.7945943069813785,
"iterations": "",
"key": "0",
},
Object {
"backgroundColor": "rgb(120, 5, 132)",
"category": "Practical",
"description": "One",
"duedate": Object {
"cond": false,
"date": "",
},
"id": 0.8857539547977513,
"iterations": "",
"key": "1",
},
Object {
"backgroundColor": "rgb(184, 10, 132)",
"category": "Practical",
"description": "Two ",
"duedate": Object {
"cond": false,
"date": "",
},
"id": 0.11232602853449736,
"iterations": "",
"key": "2",
},
],
"from": 2,
"to": 1,
}
Here I would like the object with the description "two" to change place with the object with the description "one." The keys don't matter because I give them new keys when I render during render.
The function that is doing the replacement looks like this so far:
const dragComplete = (item) => {
let itemArray = item.data;
// from object is going to be replaced with to object and visa vreca
let indexFrom = item.from;
let indexTo = item.to;
let objMovesFrom = itemArray[indexFrom];
let objMovesTo = itemArray[indexTo];
let sortedArray = itemArray;
console.log('Object moves from : ' + objMovesFrom.description);
console.log('Obejct moves to : ' + objMovesTo.description);
sortedArray.map((task, i) => {
if ((i = indexFrom)) {
sortedArray.splice(indexFrom, 1, objMovesTo);
}
if ((i = indexTo)) {
sortedArray.splice(indexTo, 1, objMovesFrom);
}
});
console.log(item);
//dispatch(setTaskList(item.data));
};
I haven't figured to make any sense of it yet...
Thx for the helpful answers!
How about just simply swapping items?..
const dragComplete = item => {
const {
from: sourceIndex,
to: targetIndex,
data: dragList,
} = item;
// // shallow `item.data` copy for a non mutating approach.
// const swapList = Array.from(dragList);
const dragItem = dragList[sourceIndex]; // swapList[sourceIndex];
const swapItem = dragList[targetIndex]; // swapList[targetIndex];
// simply swap items.
// actively mutate `item.data`. // // `item.data` remains unmutated.
dragList[targetIndex] = dragItem; // swapList[targetIndex] = dragItem;
dragList[sourceIndex] = swapItem; // swapList[sourceIndex] = swapItem;
console.log('Object moves from : ' + dragItem.description);
console.log('Object moves to : ' + swapItem.description);
// return swapList;
};
const sample = {
"data": [{
"backgroundColor": "rgb(154, 0, 132)",
"category": "Practical",
"description": "Zero",
"duedate": {
"cond": false,
"date": "",
},
"id": 0.7945943069813785,
"iterations": "",
"key": "0",
}, {
"backgroundColor": "rgb(120, 5, 132)",
"category": "Practical",
"description": "One",
"duedate": {
"cond": false,
"date": "",
},
"id": 0.8857539547977513,
"iterations": "",
"key": "1",
}, {
"backgroundColor": "rgb(184, 10, 132)",
"category": "Practical",
"description": "Two ",
"duedate": {
"cond": false,
"date": "",
},
"id": 0.11232602853449736,
"iterations": "",
"key": "2",
}],
"from": 2,
"to": 1,
};
console.log({ data: sample.data });
dragComplete(sample);
console.log({ data: sample.data });
.as-console-wrapper { min-height: 100%!important; top: 0; }
I have an array and it looks as follow:
[
{
"DT_RowId": "row_4758",
"companies": {
"id": 23,
"email": null,
"name": "test"
},
"USERS": {
"UserId": 23
}
},.....
]
How do I slice it and get only "companies": and the result as follows:
[
{
"id": 23,
"email": null,
"name": "test"
},.....
]
to clear some issues I have added the function in which I'm using data.map
fn.loadData = function (data) {
var dataKeys = Object.keys(data);
console.log(data)// 'data' is an object
console.log(data.map(x => x.companies)) ///data.map not a function error
var infiniteList = document.getElementById('infinite-list');
infiniteList.delegate = {
createItemContent: function (i) {
return ons._util.createElement(
'<ons-list-item modifier="chevron" tappable>' + data[dataKeys[i]].name + '</ons-list-item>'
);
},
countItems: function () {
return Object.keys(data).length;
}
};
infiniteList.refresh();
}
as comments told you to do:
const data = [
{
"DT_RowId": "row_4758",
"companies": {
"id": 23,
"email": null,
"name": "test"
},
"USERS": {
"UserId": 23
}
},
{
"DT_RowId": "row_3758",
"companies": {
"id": 24,
"email": null,
"name": "test3"
},
"USERS": {
"UserId": 24
}
},]
console.log(data.map(obj=>obj.companies))
This worked:
const newArray = [];
for (let i = 0; i < companyArray.length; i++) {
newArray.push(companyArray[i].companies);
}
Thanks, everyone
I have JSON looks like this:
{
"ArrayInfo": [
{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
]
}
I want to replace an object of JSON with another object.For example I have this object :
{"name":"E","Id":"5"}
and it is going to be replaced by this object of JSON:
{"name":"B","Id":"2"}
JSON should look like this :
{
"ArrayInfo": [
{
"name": "A",
"Id": "1"
},
{
"name": "E",
"Id": "5"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
]
}
What I did is to use Object.assign but the new object will be added to array instead of replacing.
(all the data is going to be dynamic but for making more understandable I use static data)
const itemToReplace = { "name": "E", "Id": "5" };
const prevItem = ArrayInfo[2]
ArrayInfo = ArrayInfo.map((el, idx) => {
return Object.assign({}, el, { prevItem: itemToReplace });
});
let NewArryInfo = ArrayInfo
console.log(NewArryInfo)
The result of console.log(NewArryInfo) :
{
"ArrayInfo": [
{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
{
"name": "E",
"Id": "5"
}
]
}
You can use Array.prototype.splice to replace an item in Array.
const replaceItem = {"name":"E","Id":"5"}
const ArrayInfo = [
{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
];
ArrayInfo.splice(1, 1, replaceItem); // remove second item and replace
console.log(ArrayInfo);
const object = {
"ArrayInfo": [{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
]
};
const objectToReplace = {
"name": "B",
"Id": "2"
};
const updatedObject = Object.assign({}, object, {
ArrayInfo: object.ArrayInfo.map((info) => {
if (info.Id === objectToReplace.Id && info.name === objectToReplace.name) {
return {
"name": "E",
"Id": "5"
};
}
return info;
})
});
console.log(updatedObject);
const myArr = [
{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
];
const replaceObj = (arr, objReplaced, objToReplaceWith) => {
const replacedObjIndex = arr.findIndex(item => JSON.stringify(item) === JSON.stringify(objReplaced));
arr[replacedObjIndex] = objToReplaceWith;
console.log(arr)
return arr;
}
replaceObj(myArr, {"name":"B","Id":"2"}, {"name":"E","Id":"5"});
In this way you can replace any object, from any position in the array.
You won't have to worry about the position of the item that you want to replace in the array and also you won't need to worry about it's keys or values.
When you map over the array you could check if each item is the one you want to replace, and if it is, return the new item instead.
ArrayInfo = ArrayInfo.map((el, idx) => {
if (el.id === prevItem.id && el.name === prevItem.name) {
return itemToReplace;
}
return el;
});
Try this!
let ArrayInfo = [{"name": "A","Id": "1"},{"name": "B","Id": "2"},{"name": "C","Id": "3"},{"name": "D","Id": "4"}];
const onReplace = {"name":"E","Id":"5"};
const toReplace = {"name": "B","Id": "2"};
function replaceArray(array, onReplace, toReplace) {
const removeIndex = array.map(item => { return item.name; }).indexOf(toReplace.name);
array.splice(removeIndex, removeIndex, onReplace);
return array
}
console.log(replaceArray(ArrayInfo, onReplace, toReplace));