I've done some research on this issue. I am trying to manipulate an array of calculated values that looks like this in the console:
{nodeVoltages: Array(11), totalPower: Array(1), xlength: Array(11)}
nodeVoltages: Array(11)
0:48
1:47.71306060387108
2:47.250273223993105
3:46.59686907269243
4:45.71876416434013
5:44.53304242029258
6:42.745236969423615
7:Complex {re: 40.38334500994142, im:1.919295696316476, __ember1513267958317: "ember368"}
8:Complex { re:39.55961661806138, im:3.8933604519196416, __ember1513267958317: "ember369"}
This array is created dynamically through some math that I've come up with so there is no input data that I can give you. I'm trying to make the above array look like this:
{nodeVoltages: Array(11), totalPower: Array(1), xlength: Array(11)}
nodeVoltages: Array(11)
0:48
1:47.71306060387108
2:47.250273223993105
3:46.59686907269243
4:45.71876416434013
5:44.53304242029258
6:42.745236969423615
7:40.38334500994142
8:39.55961661806138
Using mathjs, I was able to evaluate my expressions and dynamically add the values into an array with the array.push command and display them. However, my code breaks once the imaginary values pop up in the results of my array.
How can I remove these imaginary numbers from my array? In other words, I need to remove the "im:" parts of the values when they begin to appear before I push them to the displayed array.
I tried to do this with some code I found from a previous answer to someone else's question (How do I remove a particular element from an array in JavaScript?) splice command like this:
var nodeVoltage2 = parser.eval(expression2);
//checks if there are imaginary values and removes them
if ("im" in nodeVoltage2) {
nodeVoltage2.splice(2,1)
}
//adds value to result array for analysis
nodeVoltages.push(nodeVoltage2);
but it returns in the console that "im is not defined".
Any help is greatly appreciated!
You can use the array map function.
Basically, we loop through the array. If the item has a .re property, we take that value only. If there is no .re property, we keep the value as is.
We can either write that in shorthand, as with result using the ternary operator and arrow function, or we can write it in a slightly more verbose but traditional way, as with resultTwo
let data = [
48
,47.71306060387108
,47.250273223993105
,46.59686907269243
,45.71876416434013
,44.53304242029258
,42.745236969423615
,{re: 40.38334500994142, im:1.919295696316476, __ember1513267958317: "ember368"}
,{ re:39.55961661806138, im:3.8933604519196416, __ember1513267958317: "ember369"}
]
let result = data.map((x) => x && x.re ? x.re : x);
let resultTwo = data.map(function(elem) {
// First, we need to check that the array element is not null / undefined
// We then need to check that it has a property called re that is also not null / undefined
if (elem != null && elem.re != null) {
// Just return the property we're interested in
return elem.re;
} else {
// Return the element as is
return elem;
}
});
console.log(result);
console.log(resultTwo);
Related
I want to add data into an object, and my object contains nested data. Example data:
pageviewEvent {
client: "clientName",
page {
document_referrer: 'some http refer header data goes here',
window_height: 1920,
window_width: 1200
}
}
Some data is undefined or null and I do not want to add this undefined/null data into the object.
I made a function that works to add data to the object conditionally (if not undefined) but I can't figure out how to add data to nested objects in the function?
I could just make a bunch of if statements, but figure it's better to put the condition test into a function to reduce code size.
Example code with comment showing thinking of what I am trying but doesn't work:
//function to check if variable undefined or null, if not -> add to pageviewEvent arrayKey, variableName
function isUndefinedNull(arrayKey, variableName) {
var evalVariableName = eval(variableName);
if (evalVariableName !== undefined && evalVariableName !== null && evalVariableName !== "") {
console.log(arrayKey);
console.log(variableName);
pageviewEvent[arrayKey] = evalVariableName;
//array key could be nested, for instance pageview[page][title] or pageview.page.tile
}
}
//make event array
const pageviewEvent = { }
//add static data
pageviewEvent.client = 'neguse';
//if not null or undefined add data
isUndefinedNull('referrer.full', 'document.referrer');
//want to put data into object pageviewEvent.referrer.full or pageviewEvent[referrer][full]
Thanks for any help. I feel like this answer can help but I can't figure it out.
I recommend using the lodash function _.set(), documentation can be found here: https://lodash.com/docs/4.17.4#set
_.set( pageviewEvent, "referrer.full", "some-value" );
If you want to customise the behaviour of how nesting is handled when there's an undefined value, you can instead use _.setWith() - see https://lodash.com/docs/4.17.4#setWith
Quick one, I've 2 arrays/ objects. One contains all items the other contains selected ID's from the first array.
My question is, what is the best way to loop through both arrays find selected items from the second array and if they are true append data to first array. What I'm trying to do is append true to the first array if the ID's match.
For example something like this:
this.categories.filter(
category => {
this.user.category_ids.filter(
selected => {
if(selected == category._id) {
var data = {'selected': true};
category.push(data);
}
}
);
console.log(category);
}
);
At the moment I'm looping through categories object then through user.category_ids and if the ID's match I want to append selected: true to first array object, if this makes sense. I get error:
core.es5.js:1084 ERROR TypeError: category.push is not a function
Which I don't understand why. I've also tried splice.
Also to me this doesn't seem like best approach, because I've 12 items in first array. And if all 12 are selected, second array will have 12 items. So looping through 12 * 12 to me is little expensive, memory wise.
You can try something like this:
this.categories.map(category => {
category.selected = this.user.category_ids.indexOf(category._id) !== -1;
return category;
});
if (selected == category._id) {
category['selected'] = true;
/* you can build a interface for category
* or declare category as any
* then you can write it as the below
*/
// category.selected = true;
}
push is to add a new item to an array.
Kindly clarify if categories is an array of objects? If yes then you cant use push to add a new object since each element in the categories is an object and object don't have push method. Add new property to object instead using
category.selected=true or
category['selected']=true;
Assumptions:
this.user.category_ids is a 'array of objects' as you are using 'category._id'.
if ids match you want to add a key 'selected' whose value is true , to that object whose id is matched .
Solution:
- You are getting this error category.push is not a function because category is an object not an array ,push only works with array.
if(selected == category._id) {
category['selected']=true;
}
So I guess the title is selfexplanatory. I have some code with nested forEach loops inside it. The loops are iterating over an array of chapter objects. Each object can have multiple child nodes and they again can have multiple child nodes, and so on.
I want to end up with one array which contains nested arrays with the child nodes.
So far my code looks like this:
exports.chapter = function(req, res) {
var chapters = [],
result = [];
chapters = exports.index(req, res);
chapters.forEach(function(chapter) {
if(chapter.orphan){
result.add({
'chapter': chapter,
'children': getChildren(chapter.children)
});
}
});
function getChildren(siblings) {
var children = [];
chapters.forEach(function(chapter) {
if($.inArray(chapter, siblings)){
children.add({
'chapter': chapter,
'children': getChildren(chapter.children)
});
}
});
return children;
};
};
I don't get any errors except for my page not loading. It doesn't write anything in my console. I think it's a problem in the setup but I'm unable to find out where at the moment. Really hope you guys can help.
Most likely problem is here:
if($.inArray(chapter, siblings)){
$.inArray is a horribly misnamed method: It returns an index, or -1 if not found, not a flag as the name implies. -1 is, of course, truthy; and 0 (a valid index), is falsey, so your if probably wants to be
if($.inArray(chapter, siblings) != -1){
// We found it...
}
or possibly
if($.inArray(chapter, siblings) == -1){
// We didn't find it
}
It's a bit strange.. I don't understand why you're using 'add' instead of 'push' method. If I try to "add" an object to an array I get an usual error. Don't you?
I have an array of objects that presents as follows:
0: Object
ConsolidatedItem_catalogId: "080808"
ConsolidatedItem_catalogItem: "undefined"
ConsolidatedItem_cost: "0"
ConsolidatedItem_description: "Test Catalog Item"
ConsolidatedItem_imageFile: "27617647008728.jpg"
ConsolidatedItem_itemNumber: "1234"
ConsolidatedItem_quantity: "1"
ConsolidatedItem_source: "CAT"
ConsolidatedItem_status: "02"
ConsolidatedItem_umCode: "EA"
1: Object
ConsolidatedItem_catalogId: ""
ConsolidatedItem_catalogItem: "undefined"
ConsolidatedItem_cost: "0"
ConsolidatedItem_description: "ALARM,SHUTDOWN SYSTEM,AXIOM,XP3, 0-1500 PSIG, HIGH AND LOW PRES Testing"
ConsolidatedItem_imageFile: ""
ConsolidatedItem_itemNumber: "10008"
ConsolidatedItem_quantity: "1"
ConsolidatedItem_source: "INV"
ConsolidatedItem_status: "02"
ConsolidatedItem_umCode: "EA"
I'm trying to update and remove an object if it's added again, or update the object. Preferably update the object with the new value. My code is as follows:
var result = $.grep(finalObject, function(e) {
return e.ConsolidatedItem_itemNumber == o.ConsolidatedItem_itemNumber;
});
console.log(result);
if (result.length == 0) {
finalObject.push(o);
shoppingCounter = finalObject.length;
$('#numberShoppedItems').text(shoppingCounter);
console.log(finalObject);
} else if (result.length == 1) {
finalObject.filter(function(x){
result = x;
console.log(result);
return x == result.ConsolidatedItem_itemNumber;
});
} else {
alert('Multiples Found');
}
}
I've tried multiple ways of getting the exact object and manipulating the data, however they've all failed. I would prefer to update the object, say if CatalogItem_itemNumber held the same value, if the CatalogItem_quantity was different - add the CatalogItem_quantity values together and update the array of objects.
I don't need an exact answer, a nudge in the right direction would do wonders though. I've looked at several of the related questions over the past couple of hours but none of them seem to address the issue. If you know of a question that has an answer, feel free to just link that as well. I may have missed it.
No Underscore.js please
When you find the matching record, you may update it by using $.extend
$.extend(result[0], o)
This will update the object in finalObject array in-place.
Alternatively, if you want to use the filter, you will need to insert the new object in the array.
finalObject = finalObject.filter(function(x) {
return x !== result[0];
});
finalObject.push(o)
Here we are allowing all the records that are not not equal to result to be returned in the resultant array that is received in finalObject. In next line, we are adding the new record.
Solved in the following manner:
1.) Verify object is not empty.
2.) Use .some() on object to iterate through it.
3.) Check if the finalObject, which is now e, has a match for the key in my temporary object I assemble, o.
4.) Update the values that need updating and return true;
Note: Originally I was going to remove the object by its index and replace it with a new object. This too can work by using .splice() and getting the index of the current object in that array you're in.
Here is the updating version:
if (o.ConsolidatedItem_quantity != '') {
var result = $.grep(finalObject, function(e) {
return e.ConsolidatedItem_itemNumber == o.ConsolidatedItem_itemNumber;
});
if (result.length == 0) {...}
else {
finalObject.some(function (e) {
if(e.ConsolidatedItem_itemNumber == o.ConsolidatedItem_itemNumber){
var a;
a = +e.ConsolidatedItem_quantity + +o.ConsolidatedItem_quantity;
e.ConsolidatedItem_quantity = a.toString();
document.getElementById(o.ConsolidatedItem_itemNumber).value=a;
return true;
};
});
}
}
I have a grid of pictures on a page. And, periodically, I want to randomly swap one out for one of 50 I have in an array of Objects- but only if they're not already in the grid. This last part is what my code is failing to do.
I first get all 50 items, and put them into an allmedia array:
// initialize
var allmedia = getAllMedia();
var imagesInGrid = [];
When I place the items in the grid, I add to an array of grid items:
imagesInGrid.push(allmedia [i]); // while looping to fill DOM grid
Then, every 8 seconds I run a getRandomImage() routine that randomly gets an image from the allmedia array and then tests it to see if it's not already in the DOM.
function getRandomImageNotInGrid(){
var randomNumber = Math.floor(Math.random() * allmedia.length);
if (!isInArray(allmedia[randomNumber], imagesInGrid)) {
return allmedia[randomNumber];
} else {
return getRandomImageNotInGrid();
}
}
function isInArray(item, arr) {
if(arr[0]===undefined) return false;
for (var i=arr.length;i--;) {
if (arr[i]===item) {
return true;
}
}
return false;
}
But when I step through the code the (arr[i]===item) test is failing. I can see that the two objects are exactly the same, but the === isn't seeing this as true.
Is this a ByReference / ByValue issue? What am I doing wrong?
console.log:
arr[i]===item
false
arr[i]==item
false
typeof item
"object"
typeof arr[i]
"object"
Edit::
In the output below, I don't understand why arr[0] is not the same as 'item'. I use the exact same object that I put into allmedia as I do when I place the item into the page and, accordingly update imagesInGrid.
console.dir(arr[0]);
Object
caption: Object
comments: Object
created_time: "1305132396"
filter: "Poprocket"
id: "69204668"
images: Object
likes: Object
link: "http://instagr.am/p/EH_q8/"
location: Object
tags: Array[2]
type: "image"
user: Object
__proto__: Object
console.dir(item);
Object
caption: Object
comments: Object
created_time: "1305132396"
filter: "Poprocket"
id: "69204668"
images: Object
likes: Object
link: "http://instagr.am/p/EH_q8/"
location: Object
tags: Array[2]
type: "image"
user: Object
__proto__: Object
Instead of randomly selecting one from allmedia, can you instead remove one from allmedia?
var randomNumber = Math.floor(Math.random() * allmedia.length);
imagesInGrid.push(allmedia.splice(randomNumber,1));
When you use ===, you are comparing the objects by reference. What type of objects are you using to compare? Are you sure they are the same object reference? For example, if you are using strings, you may want to use == instead of ===. If you are using DOM objects, you will want to compare the source, as Alxandr suggested.
Also, your for loop syntax appears to be wrong:
for (var i=arr.length;i--;)
Should be:
for (var i=arr.length - 1; i >= 0; i--)
...if I'm not mistaken.
You don't show any code for how the image "objects" are created or how they are added and removed from the DOM. If you are creating image elements and storing references in an array, then replacing the DOM element with the one from the array, then the comparision should work.
However, if your image object is a bundle of data that is used to create an image element for display, then they will never be equal to each other. Every javascript object is unique, it will only ever be equal to itself.
But I suspect the simplest solution is that suggested by ic3b3rg - remove the object from allMedia when you select it, that way you don't have to test if it's already in imagesInGrid because you can only select each image once. If you want the display to go on forever, then when allmedia is empty, put all the images from imagesInGrid back into it and start again.
Edit
Your problem is the for loop. When you set :
for (var i=arr.length;i--;) {
// On first iteration, i=arr.length
// so arr[i] is undefined
}
i is not decremented until after the first loop, so set i=arr.length-1. It is more common to use while with a decrementing counter:
var i = arr.length;
while (i--) {
// i is decremented after the test
}