This is basically something that makes zero logical sense, and I'm not sure why this is happening.
When you create a function to compare attribute values of an array of objects (essentially JSON object), it refuses to find the index. However, OUTSIDE the function, it seems to work perfectly fine.
However, the problem is
var peoples = [
{ "name": 44, "dinner": "pizza" },
{ "name": 65, "dinner": "sushi" },
{ "name": 33, "dinner": "hummus" }
];
var val = 33;
$("#t").append(get_index_of_array_based_on_value(peoples, val));
function get_index_of_array_based_on_value(array, val) {
$.each(array, function (index, obj) {
$.each(obj, function (attr, value) {
console.log(" attr: " + attr + " == " + value + " (" + val + ") {{" + index + "}} ");
if (value == val) {
return index;
}
});
});
}
http://jsfiddle.net/QStkd/2327/
The above does not work.
The below script does work.
http://jsfiddle.net/QStkd/2330/
The below script is simply the same script except outside the function. When you put stuff into functions it suddenly refuses to find the index based on the value.
You cannot return a value from a $.each call. You are inside a callback, your return doesn't affect the main function.
When you use return inside the $.each callback, it's similar to break/continue in a for/while loop. A falsy value will break the loop, and a truthy value is like calling continue.
You need to return from the main function, get_index_of_array_based_on_value, not from the $.each.
function get_index_of_array_based_on_value(array, val) {
var returnVal = null;
$.each(array, function (index, obj) {
$.each(obj, function (attr, value) {
console.log(" attr: " + attr + " == " + value + " (" + val + ") {{" + index + "}} ");
if (value == val) {
returnVal = index;
return false; // break;
}
});
if(returnVal !== null){
return false; // break the outer loop
}
});
return returnVal;
}
thy this
var peoples = [
{ "name": 44, "dinner": "pizza" },
{ "name": 65, "dinner": "sushi" },
{ "name": 33, "dinner": "hummus" }
];
var val = 33;
$("#t").append(get_index_of_array_based_on_value(peoples, val));
function get_index_of_array_based_on_value(array, val) {
for(var index = 0; index < array.length; index++){
for(var attr in array[index]) {
var value = array[index][attr];
console.log(" attr: " + attr + " == " + value + " (" + val + ") {{" + index + "}} ");
if (value == val) {
return index;
}
}
}
}
Related
Using Javascript, I wrote this code to create an object:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
Now, i'm interested in printing each property & its value so i wrote this code:
for (let eachEle in employee){
if(typeof eachEle=='string' || typeof eachEle=='number'){
console.log(eachEle + ":" + employee[eachEle]);
}
else if(typeof eachEle=='function'){
console.log(eachEle + ":" + employee.eachEle());
}
}
But, on executing, it works fine except for "emp_fullname" & "emp_bonus". Instead of showing the value, it shows me the function:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function() {
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal: "QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary: 13579,
emp_bonus: function() {
return (this.emp_salary * 1);
}
};
for (let eachEle in employee) {
if (typeof eachEle == 'string' || typeof eachEle == 'number') {
console.log(eachEle + ":" + employee[eachEle]);
} else if (typeof eachEle == 'function') {
console.log(eachEle + ":" + employee.eachEle());
}
}
How am I supposed to retrieve the value for those two properties? I'm looking for answers using which I can modify the for...in loop & retrieve the value.
How am i supposed to retrieve the value for those two properties?
The function is the value of those properties. If you want to get the return value of the function, you have to call it.
Note that the typeof check you're doing in your for-in loop is unnecessary. The eachEle variable is the property name, not the property value. In a for-in loop, the name will always be a string. (Not all properties are named with strings, but for-in only covers the ones that are.)
You want to get the value of the property, check if it's a function, and if so call it:
for (let name in employee){
let value = employee[name];
if (typeof value === "function") {
value = employee[name]();
}
console.log(name + ":" + value);
}
Live Example:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
for (let name in employee){
let value = employee[name];
if (typeof value === "function") {
value = employee[name]();
}
console.log(name + ":" + value);
}
You said you just wnated to change the loop, but another approach is to change the object definition to use an accessor property rather than an explicit function:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
get emp_fullname() {
// ^^^ ^^
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
get emp_bonus() {
// ^^^ ^^
return (this.emp_salary*1);
}
};
Then the loop doesn't have to check:
for (let name in employee){
console.log(name + ":" + employee[name]);
}
Live Example:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
get emp_fullname() {
// ^^^ ^^
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
get emp_bonus() {
// ^^^ ^^
return (this.emp_salary*1);
}
};
for (let name in employee){
console.log(name + ":" + employee[name]);
}
That works because when you get the value of an accessor property, its accessor function is run behind the scenes and that function's return value is provided as the property value.
You need to check the type of value, eachEle is value of key which for your object is always string.
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function() {
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal: "QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary: 13579,
emp_bonus: function() {
return (this.emp_salary * 1);
}
};
for (let eachEle in employee) {
if (typeof employee[eachEle] == 'string' || typeof employee[eachEle] == 'number') {
console.log(eachEle + ":" + employee[eachEle]);
} else if (typeof employee[eachEle] == 'function') {
console.log(eachEle + ":" + employee[eachEle]());
}
}
Two things you need to change
You need to check for the value of element for string, number and function and not the key
While executing the function you need to use the brackets notation since its a dynamic key
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
for (let key in employee){
let eachEle = employee[key];
if(typeof eachEle=='string' || typeof eachEle=='number'){
console.log(key + ":" + employee[key]);
}
else if(typeof eachEle=='function'){
console.log(key + ":" + employee[key]());
}
}
Your mistakes are:
1. You wrote: typeof eachEle insted of: typeof employee[eachEle]:
2. The execute is: employee.eachEle() insted of employee[eachEle](). eachEle is a string.
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
for (let eachEle in employee){debugger
if(typeof employee[eachEle]=='string' || typeof employee[eachEle]=='number'){
console.log(eachEle + ":" + employee[eachEle]);
}
else if(typeof employee[eachEle]=='function'){
console.log(eachEle + ":" + employee[eachEle]());
}
}
In your for loop, you iterate over the keys in the object, and those will never be objects. Instead, you should retrieve the item before checking its type.
for(let key in employee){
let value = employee[key];
if(typeof value=='string' || typeof vlaue=='number'){
console.log(key + ":" + value);
}
else if(typeof value=='function'){
console.log(key + ":" + value());
}
}
{
field_country: ["England", "Netherlands", "India", "Italy"],
field_continent: ["Europe"],
field_group: ["Building", "People", "Landscape"
}
I want to loop over each item and return the key and the array together with ending 'OR' for example:
field_country: "England" OR field_country: "Netherlands"
The last item should not end with 'OR' in the loop. I am not sure what the best process is for this using vanilla JS. So far my code is as follows:
Object.keys(facets).forEach(function(facetKey) {
if (facets[facetKey].length > 1) {
facetResults = facets[facetKey];
for (var i = 0; i < facetResults.length; i ++) {
if (i == 1) {
filter = "'" + facetKey + "'" + ":'" + facetResults[i] + " OR";
return filter;
} else {
filter = "'" + facetKey + "'" + ":'" + facetResults[i];
}
}
} else {
filter = "'" + facetKey + "'" + ": " + facets[facetKey] + "'";
return filter;
}
});
I would be very grateful for any assistance.
Thanks in advance.
You can do something like this with Object.entries and Array.reduce if you would like to get the final result in the form of an object:
const data = { field_country: ["England", "Netherlands", "India", "Italy"], field_continent: ["Europe"], field_group: ["Building", "People", "Landscape"] }
const result = Object.entries(data).reduce((r, [k, v]) => {
r[k] = v.join(' OR ')
return r
}, {})
console.log(result)
It is somewhat unclear what is the final format you need to result in but that should help you to get the idea. If ES6 is not an option you can convert this to:
const result = Object.entries(data).reduce(function(r, [k, v]) {
r[k] = v.join(' OR ')
return r
}, {})
So there are is no arrow function etc.
The idea is to get the arrays into the arrays of strings and use the Array.join to do the "replacement" for you via join(' OR ')
Here's the idea. In your code you are appending " or " at the end of your strings starting at index 0. I suggest you append it at the the beginning starting at index 1.
var somewords = ["ORANGE", "GREEN", "BLUE", "WHITE" ];
var retval = somewords[0];
for(var i = 1; i< somewords.length; i++)
{
retval += " or " + somewords[i];
}
console.log(retval);
//result is: ORANGE or GREEN or BLUE or WHITE
Your conditional expression if (i == 1) would only trigger on the second iteration of the loop since i will only equal 1 one time.
Try something like:
if (i < (facetResults.length - 1)) {
// only add OR if this isn't the last element of the array
filter = "'" + facetKey + "'" + ":'" + facetResults[i] + " OR";
return filter;
}
Here's your updated code:
Object.keys(facets).forEach(function(facetKey) {
if (facets[facetKey].length > 1) {
facetResults = facets[facetKey];
for (var i = 0; i < facetResults.length; i ++) {
if (i < (facetResults.length - 1)) {
filter = "'" + facetKey + "'" + ":'" + facetResults[i] + " OR";
return filter;
} else {
filter = "'" + facetKey + "'" + ":'" + facetResults[i];
}
}
} else {
filter = "'" + facetKey + "'" + ": " + facets[facetKey] + "'";
return filter;
}
});
I'm having trouble producing a script to match an object's value in object array based on an object's value in a separate array, and retrieve a separate value from that object.
I have used standard for-loops and the current iteration in jQuery each.
I have also tried setting the if statement to look for the two values as ==, but it always produces non matches (or -1).
Can anyone steer me in the right direction here?
transfers = [
{Package: "1", Origin_Facility = "a"},
{Package: "2", Origin_Facility = "b"}
];
storeData = [
{fromPackage: "1,6,26"}
]
var storeDataEach = function( sx, sxv ) {
var transfersEach = function( sy, syv ) {
if(storeData[sx].fromPackage.indexOf(transfers[sy].Package) > -1){
var facilityStore = transfers[sx].Origin_Facility;
storeData[sx].origin = facilityStore + " + " + transfers[sy].Package + ' + ' + storeData[sx].fromPackage;
return false;
} else {storeData[sx].origin = 'error' + transfers[sy].Package + " + " + storeData[sx].fromPackage;return false;}
};
jQuery.each(transfers, transfersEach);
}
jQuery.each(storeData, storeDataEach);
The main problem is you are returning false from the $.each loop which will stop the iteration
A crude fix is to remove the return from else block
var storeDataEach = function(sx, sxv) {
var transfersEach = function(sy, syv) {
if (storeData[sx].fromPackage.indexOf(transfers[sy].Package) > -1) {
var facilityStore = transfers[sx].Origin_Facility;
storeData[sx].origin = facilityStore + " + " + transfers[sy].Package + ' + ' + storeData[sx].fromPackage;
return false;
} else {
storeData[sx].origin = 'error' + transfers[sy].Package + " + " + storeData[sx].fromPackage;
}
};
jQuery.each(transfers, transfersEach);
}
But this still have problems with the data structure, in your example you have 26 in the fromPackage, now if you have a package value of 2 that also will return a positive result
I have a ajax returning data some times like
{
"results": [{
"symbol": "AppConomy",
"Name": null,
"PriceSales": null
}]
}
for above my forEach function is working fine but when same data is returning
{
"results": {
"symbol": "AppConomy",
"Name": null,
"PriceSales": null
}
}
my forEach function not working
$.get(url, function(data){
var x =data['results'];
x.forEach(function logArrayElements(element, index, array) {
$(self).append('<button class="tag-format" title="'+array[index].Name+'" style="color:#fff;background-color:rgb(0,151,216);border:1px solid;border-radius:10px;"> '+ array[index].symbol +" - "+ array[index].PriceSales +' </button>');
});
});
That's because your JSON isn't an array. You can easily check beforehand using Array.isArray(). You should also be using getJSON if the data you are retrieving is in fact JSON.
$.getJSON(url, function(data) {
var x = data.results;
if(Array.isArray(x)) {
x.forEach(function logArrayElements(element, index, array) {
$(self).append('<button class="tag-format" title="' + array[index].Name + '" style="color:#fff;background-color:rgb(0,151,216);border:1px solid;border-radius:10px;"> ' + array[index].symbol + " - " + array[index].PriceSales + ' </button>');
});
} else {
$(self).append('<button class="tag-format" title="' + x.Name + '" style="color:#fff;background-color:rgb(0,151,216);border:1px solid;border-radius:10px;"> ' + x.symbol + " - " + x.PriceSales + ' </button>');
}
});
Your forEach is for iterating over an array. In your second JSON, there is no array to iterate over, so you need to call the function directly on data['results']:
$.get(url, function(data){
var x = data['results'],
addButton = function(item) {
$(self).append('<button class="tag-format" title="'+array[index].Name+'" style="color:#fff;background-color:rgb(0,151,216);border:1px solid;border-radius:10px;"> '+ array[index].symbol +" - "+ array[index].PriceSales +' </button>');
};
if(Array.isArray(x)) {
x.forEach(function logArrayElements(element, index, array) {
addButton(array[index]);
});
} else {
addButton(x);
}
});
Javascript object is not an Array.
Html
<div id="results"></div>
Javascript
var firstArray = {
"results": [{
"symbol": "AppConomy",
"Name": null,
"PriceSales": null
}]};
var secondArray = {
"results": {
"symbol": "AppConomy",
"Name": null,
"PriceSales": null
}};
//Result: 1
$("#results").append("<span>FirstArray result: " + firstArray['results'].length + "</span><br/>");
//Result: undefined
$("#results").append("<span>FirstArray result: " + secondArray['results'].length + "</span><br/>");
I have the following array
array = [
{
"id": "67",
"sub": [
{
"id": "663",
},
{
"id": "435",
}
]
},
{
"id": "546",
"sub": [
{
"id": "23",
"sub": [
{
"id": "4",
}
]
},
{
"id": "71"
}
]
}
]
I am currently looping throught the array as follows
calling the array:
processArray(array);
the function loop
function processArray(arr)
{
for(var item in arr) {
var value = arr[item];
var order = item;
var itemID = value.id;
if(itemID != null)
{
$('.text').append(" ORDER : " + order + " Item ID : " + itemID + "<br />" );
}
if(typeof(value) == 'object') { //If it is an array,
processArray(arr[item]);
}
}
}
Currently i am getting the order of the item and the current ID no problem. What i need however (for my database schema) is for each item get the ID of its parent if there is one.
Do i need to pass the parent to each node? Or is there an easier way?
Thanks
Working demo
Include an optional parameter parentID in the function; by doing this, you can still use the processArray(array); syntax to process the original array.
function processArray(arr, parentID)
{
for(var item in arr) {
var value = arr[item];
var order = item;
var itemID = value.id;
if(itemID != null)
{
var output = " ORDER : " + order + " Item ID : " + itemID;
if( parentID ) { output += " PARENT : " + parentID; }
$('.text').append( output + "<br />");
}
// PROCESS SUB-ARRAY
if( typeof(value.sub) == 'object') { //If it is an array,
processArray( value.sub, itemID );
}
}
}
Use an auxiliary function that has id as part of its signature:
function processArray(arr) {
function _processArray(arr, id) {
for (var item in arr) {
var value = arr[item];
var order = item;
var itemID = value.id; // you need to change this because on the second call you pass in a string and not just an object
var parentId = id;
// Commenting the if statement that you had here actually shows the parent id's now.
$('.text').append(" ORDER : " + order + " Item ID : " + itemID + " Parent Id : " + parentId + "<br />");
if (typeof value === "object") { //use instanceof,
_processArray(arr[item], itemID);
}
}
}
_processArray(arr, 0);
}