Js copy objects from array without reference - javascript

I hava a problem with copy a objects to array. I think it is an problem with reference.
In my program i have few array. First is dataForMonth - it is array of objects with data for month. And second is an products array which contains products objects. Product have property forecastArry wchich is array of objects.
Here code :
this.allProducts.map(function (product) {
var dataForMonth = data.filter(function (e) {
return e.dataId === product.productDataId;
});
var z = { posId: product.sales_plan_pos_id, arry: [] }
for (var sheetMonth of sheet.channels) {
var result = dataForMonth.filter(function (e) {
return e.CHANNEL === sheetMonth.CHANNEL;
});
product.forecastArry[someId].channels = result;
);
The problem is that the every changed channels property have the same value - its a value from last product?
Anybody know how to fix it ?

Seems like you want to edit each product in this.allProducts. So you want to add a return value to your map. You should also use let so that the scope of variables declared is preserved within map function, although I believe the map function already takes care of that. In addition, not that you have to reassign this.allProducts to your map function call. So your answer should be something like the following:
this.allProducts = this.allProducts.map(function (product) {
let dataForMonth = data.filter(function (e) {
return e.dataId === product.productDataId;
});
let channelsForMont = [];
let z = { posId: product.sales_plan_pos_id, arry: [] }
for (let sheetMonth of sheet.channels) {
let result = dataForMonth.filter(function (e) {
return e.CHANNEL === sheetMonth.CHANNEL;
});
product.forecastArry[someId].channels = channelsForMont;
return product;
);
P.S Your original code has some missing brackets and result variable is unused. You should do something about them.

Related

Get payload from String

I have this String:
['TEST1-560', '{"data":[{"price":0.0815,"volume":0.2,"car":"BLUE"}],"isMasterFrame":false}']
I want to get the keys 'TEST1-560' which is always fist and "car" value.
Do you know how I can implement this?
This is a very, very scuffed code, but it should work for your purpose if you have a string and you want to go through it. This can definitely be shortened and optimized, but assuming you have the same structure it will be fine.:
// Your data
var z = `['TEST1-560', '{"data":[{"price":0.0815,"volume":0.2,"car":"BLUE"}],"isMasterFrame":false}']`;
var testName = z.substring(2).split("'")[0];
var dividedVar = z.split(",");
for (var ind in dividedVar) {
if (dividedVar[ind].split(":")[0] === '"car"') {
var car = dividedVar[ind].split(":")[1].split("}")[0].substring(1,dividedVar[ind].split(":")[1].split("}")[0].length-1);
console.log(car)
}
}
console.log(testName);
output:
BLUE
TEST1-560
In a real application, you don't need to log the results, you can simply use the variables testName,car. You can also put this in a function if you want to handle many data, e.g.:
function parseData(z) {
var testName = z.substring(2).split("'")[0];
var dividedVar = z.split(",");
for (var ind in dividedVar) {
if (dividedVar[ind].split(":")[0] === '"car"') {
var car = dividedVar[ind].split(":")[1].split("}")[0].substring(1, dividedVar[ind].split(":")[1].split("}")[0].length - 1);
}
}
return [testName, car]
}
This will return the variables values in an array you can use
const arr = ['TEST1-560', '{"data":[{"price":0.0815,"volume":0.2,"car":"BLUE"}],"isMasterFrame":false}']
const testValue = arr[0];
const carValue = JSON.parse(arr[1]).data[0].car;
console.log(testValue);
console.log('-----------');
console.log(carValue);
If your structure is always the same, your data can be extracted like above.

getting confused with trying to insert nesting objects

Currently trying to build a javascript form that converts the inputs into JSON. I've managed to create objects that allow multiple keys/values to be entered however I'm struggling to get my head around the logic and code for nesting a child object within an object.
let objects = [];
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('btn2').addEventListener('click', function(e) {
e.preventDefault();
let infoBoxOne = document.getElementById('key').value // store the key into a variable
let infoBoxTwo = document.getElementById('value').value // store the value into a variable
const lastObject = objects[objects.length-1] // finds the last object in the objects array
const objectValues = Object.entries(lastObject) // gets all the keys and values
const lastKeyValuePair = values[values.length-1]; // stores the last key and value entered into a variable
})
})
So my initial idea was to find the last key/value within the last object that was added and use something like Object.create() or push() to insert the data. Is there an easier way of achieving this?
edit: here's a jsfiddle showing what I have exactly so far https://jsfiddle.net/9jrzLxnm/
Secone edit: idea of what I'm trying to achieve
{
{
"firstObject":'FirstObject'
},
{
"lastObject": {
"infoBoxOne": "JlastObject",
},
}
}
Ok firstly you have to set the desired location to place a child object as an object itself.. then the rest is intuitive
My example is on jsfiddle
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('btn2').addEventListener('click', function(e) {
e.preventDefault();
let childKey = document.getElementById('key').value // store the key into a variable
let childValue = document.getElementById('value').value // store the value into a variable
const lastObject = objects[objects.length-1] // finds the last object in the objects array
const values = Object.entries(lastObject) // gets all the keys and values
const [key,value] = values[values.length-1]; // stores the last key and value entered into a variable
lastObject[key]={} //turning place to put child into an object
lastObject[key][childKey]=childValue //placing the nested child
document.forms[0].reset();
listToJson();
})
})

Javascript filter deep array in array while maintaining original array

I'm wanting to filter an array without changing the original array that I've sliced from. You can see that the first thing I do within the filterChange function is to splice from the original array. The original array still ends up changed as well and I don't understand why.
var MenuDisplayModule = (function ($, window, document, Handlebars) {
var module = {};
module.menuItems = [];
module.init = function () {
console.info('BreadcrumbDisplayModule Init');
};
module.template = function (array) {
module.menuItems = array;
var filteredMenuItems = array.slice(0);
_template(filteredMenuItems);
}
module.filterChange = function (filterText) {
var filteredMenuItems = module.menuItems.slice(0);
filteredMenuItems.forEach(function (item, index) {
var filteredItems = item.MenuItems.filter(function (el) {
return (el.MenuText.includes(filterText));
});
filteredMenuItems[index].MenuItems = filteredItems;
})
_template(filteredMenuItems);
}
function _template(filteredMenuItems) {
var menu_items_source = $("#menu-items-template").html();
var menu_items_template = Handlebars.compile(menu_items_source);
$("#menu-items-placeholder").empty().html(menu_items_template({ menuItems: filteredMenuItems }));
}
return module;
}(window.jQuery, window, document, window.Handlebars));
So it appears I didn't understand splice. Specifically the shallow aspect of it. Since I was wanting to filter on a sub array of the array I was trying to copy I ended up not getting an actual copy.
Instead of copying the array I'm creating a new array and pushing the results of the filter to it. Taking with it the un-filtered properties from the original array.
module.filterChange = function (filterText) {
var filteredMenuItems = [];
module.menuItems.forEach(function (item, index) {
var filteredItems = item.MenuItems.filter(function (el) {
return (el.MenuText.includes(filterText));
});
filteredMenuItems.push({
HeaderText: item.HeaderText,
ID: item.ID,
MenuItems: filteredItems
})
})
_templateOnChange(filteredMenuItems);
}
If you want to filter the Array and create a new one with the filtered contents and leave the old one unchanged I suggest
newArray = oldArray.filter(function(item) { return item.wantThis === true; })
Now you have newArray consisting of only those Objects which have property
item.wantThis === true
In you example you are using slice() which in my experience looks very much like splice() (which will can mutate the Array).
I suggest you simply stick to using filter().
But why are you making so many slice copies?
It would help if you posted an example of an Object in the array you receive.
Form looking at you example it seems that filteredItems is a private var to the previous ForEach loop, if you change that active part of your code to....
module.filterChange = function (filterText) {
var filteredMenuItems = module.menuItems.slice(0);
var filteredItems; // declare the var outside of the .forEach
filteredMenuItems.forEach(function (item, index) {
filteredItems = item.MenuItems.filter(function (el) {
return (el.MenuText.includes(filterText));
});
filteredMenuItems[index].MenuItems = filteredItems;
})
_template(filteredMenuItems);
}
It might work.
The effect of your filteredItems is..
filteredMenuItems.forEach(function(item) {
item.MenuItems = item.MenuItems
.filter(function(el) { return (el.MenuText.includes(filterText)); });
})
So your item.MenuItems will get smaller with each filter.

Return Object in Array if Property Match

Here is the scenario:
There is a parameter titledlistOfSelectedProductIdsthat contains
all of the selected ids.
There is another list titled listOfAllPossibleProducts, which
contains a list of objects. That object contains a ProductId,
ProductName, and ProductCode. It looks something like this:
The task at hand:
I need to loop through my listOfSelectedProductIds. If the ProductId matches a ProductId from listOfAllPossibleProducts, then I need to return that object.
Here is what I am doing:
function SelectedProducts(listOfSelectedProductIds){
for (var index = 0; index < listOfSelectedProductIds.length; index++) {
var currentItem = listOfSelectedProductIds[index];
var desiredProduct = _.contains(listOfAllPossibleProducts, currentItem);
if (desiredProduct === true) {
return listOfAllPossibleProducts[index];
}
}
}
What's currently happening:
My loop is getting the selected id as expected i.e. currentItem, but _.contains(...)
always returns false.
Question:
What is the best way to find the objects in
listOfAllPossibleProducts that have ProductIds that match my
ProductIds in the listOfSelectedProductIds
How about using _.filter:
var result = _.filter(listOfAllPossibleProducts, function (el) {
return _.contains(listOfSelectedProductIds, el.id);
});
Or the non-underscore method:
var result = listOfAllPossibleProducts.filter(function (el) {
return listOfSelectedProductIds.indexOf(el.id) > -1;
});
DEMO
create another structure productsByProductId once!
var productsByProductId = {};
listOfAllPossibleProducts.forEach(p => {
productsByProductId[p.ProductId()] = p
});
and maybe a helper function
function getProductById(id){
return productsByProductId[id];
}
and use this to map the ids to the nodes
var selectedProducts = listOfSelectedProductIds.map(getProductById)

Creating a new array combining two existing objects through iteration with condition in jQuery

I have a main object consisting of two main properties, data which contains messages and included which contains the senders of the messages. I want to create a new Array called messages which will contain all the values of both objects but in a way that every object inside this array will consist of the data values adding the correct sender as property to each of them.
I am able to separate the main object to two different ones, one containing the data and the other containing the senders.
if (jsonAPI.data) {
$.each(jsonAPI.data, function(index, value) {
dataObj[index] = value;
});
}
if (jsonAPI.included) {
$.each(jsonAPI.included, function(index, value) {
senders[value.id] = value;
});
}
I guess I have to make an iteration for every value of the dataObj and check if the relationships.sender.data.id is equal to senders.id then add the new property to dataObj, but I don't know how to write it.
What I say can be more clear in this fiddle https://jsfiddle.net/mosmic/f2dzduse/
Working jsfiddle: https://jsfiddle.net/f2dzduse/5/
var jsonAPI = {<snip>};
var dataObj = {};
if (jsonAPI.data) {
$.each(jsonAPI.data, function(index, value) {
dataObj[index] = value;
});
}
$.each(dataObj, function(index, value) {
//Prevent error if there is no sender data in included
if(jsonAPI.included.length - 1 >= index) {
//check if ids are equal
if(value.relationships.sender.data.id == jsonAPI.included[index].id) {
value.sender = jsonAPI.included[index];
}
}
});
console.log(dataObj);
This code assumes that jsonAPI.data.relationships.sender.data.id and jsonAPI.included.id are both in the same order!
If this is not always the case let me know and I'll rewrite the code to loop trough each jsonAPI.data and then loop trough jsonAPI.include to check for an equal id. This code will be slower since it will loop a total of jsonAPI.data.length X jsonAPI.include times.
Here's the updated code: https://jsfiddle.net/f2dzduse/6/
var jsonAPI = {<snip>};
var dataObj = [];
$.each(jsonAPI.data, function(x, data) {
dataObj[x] = data;
$.each(jsonAPI.included, function(y, included) {
if(data.relationships.sender.data.id == included.id) {
dataObj[x].sender = included;
}
});
});
console.log(dataObj);

Categories