I have the following and I am trying to figure out how to search the array of objects - the call() function is called multiple times ?
var arr = [];
var newData;
function call() {
newData = $('a').attr('href');
if($.inArray(newData, arr) == -1) {
$.post('/blah', function(data) {
arr.push(data);
});
}
}
data is like [object{ }] so arr becomes [[object{id='1', myUrl=''}], [object{id='2', myUrl='' }]].
What I am trying to figure is out whether newData is contained within the arr ?
If the array contains objects, $.inArray will not work. This is because objects are only equal if they are the same object, not just contain the same values.
$.inArray won't work here also because newData is a string. It's not gonna search inside each object for you, you need to that yourself, with your own loop.
Something like this:
newData = $('a').attr('href');
$.each(arr, function(){
if(this.myUrl === newData){
$.post('/blah', function(data) {
arr.push(data);
});
return false; // break once a match is found
}
});
The Array arr will contain a list of objects. Why would newData be "contained" within the arr? They are two separate variables.
Update - Upon further inspection this line is no good:
if($.inArray(newData, arr) == -1) {
You are essentially saying look for newData in the arr (which is empty).
Update - Here is some sample code that should work. Here I am treating data as a plain old object (not an array of objects) with a property named "url".
http://jsfiddle.net/nWh6N/
Related
I have an json object:
json = {
"array": [80, 50]
}
A third party jsoneditor, returns a path variable as a list of strings or index to the value. I use event listeners to detect changes to the value and I store those changes in a separate object to later submit to a form.
For example, if I change 50 to 60, this is what is returned:
node.path = ["array", 1]
node.value = 60
I am using reduceRight() to normally map the changes to the object to the changed object, however when the value is an Array it is converting the array to an object.
let delta = node.path.reduceRight((obj, elem) => ({[elem]: obj}), node.value)
//returns
delta = {array: {1: 60}}
//instead of
delta = {array: [80, 60]}
How can I check the original json and if the field is an Array object, don't reduce this into an object but keep the original Array and update the Array with the changed value within the Array? I need to submit the entire array into the form.
EDIT:
I know that I can do some custom logic within the reduce to check the original json and get the unchanged part of the array. I just dont know how to achieve that
let delta = node.path.reduceRight( function (obj, elem) {
//some logic here to account for arrays and get original array list and change only slected index
else {
return {[elem]: obj}), node.value
}
});
EDIT:
Alternatively, how can can I get the nested keys from the node.path and find the original array and then just update the array index? The path can sometimes be nested sothe path is always going to be the Array-like structure.
//this does not work
let orig_key_val = json[node.path]
Thanks!
This seems to work, finally... I used a regular reduce() and check if the key is an Array if it is store my original Array into a tmp object and save that key. The next time the reduce() comes around, if the index is on the last path element then set the tmp[tmp_key][key] to my target value and return the adjusted for Array object instead.
I can see how this will not work for nested json objects but for now I dont have any... Unless someone can show me how to figure that one out this is my implementation for now.
let tmp = {};
let tmp_key;
let delta = node.path.reduce((val, key, index, array) => {
if (Array.isArray(json[key])) {
tmp[key] = json[key]
tmp_key = key;
} else if (Object.keys(tmp).length !== 0 && index === node.path.length-1) {
tmp[tmp_key][key] = node.value;
return tmp
} else
return {[key]: val}
}, node.value);
In the code below, I'm trying to search the JSON output for a specific string (for example 'name_col_lbl') and return its value (in this case 'Name') for AngularJS to ouptut in the view.
$scope.globalContent = [
{"id":"1","module":"student_reg","item":"name_col_lbl","value":"Name"},
{"id":"2","module":"student_reg","item":"bday_col_lbl","value":"Birthdate"}
]
angular.forEach($scope.globalContent, function(el){
$scope.nameLbl = el ***This is where I need to search for the string and return its value***;
$scope.bdayLbl= el ***This is where I need to search for the string and return its value***;
});
I can't seem to find an efficient way to handle this. Thanks in advance!
This should do the trick:
var $scopeglobalContent = [
{"id":"1","module":"student_reg","item":"name_col_lbl","value":"Name"},
{"id":"2","module":"student_reg","item":"bday_col_lbl","value":"Birthdate"}
];
for(var i = 0; i < $scopeglobalContent.length; i++){
for(key in $scopeglobalContent[i]){
if($scopeglobalContent[i][key] == "name_col_lbl"){
return console.log($scopeglobalContent[i].value);
}
}
}
This is basic stuff. I suggest you read on objects and loops to get a better understanding of how this works and how to use it.
From this stackoverflow answer, here's how you can search an array of objects:
var obj = array.filter(function ( obj ) {
return obj.item === "name_col_lbl";
});
obj will contain either the value of name_col_lbl or undefined if the key doesn't exist.
So your code would look like this:
function findObject(array, keyName) {
var obj = array.filter(function ( obj ) {
return obj.item === keyName;
})[0];
return obj;
}
$scope.globalContent = [
{"id":"1","module":"student_reg","item":"name_col_lbl","value":"Name"},
{"id":"2","module":"student_reg","item":"bday_col_lbl","value":"Birthdate"}
]
angular.forEach($scope.globalContent, function(el){
$scope.nameLbl = findObject($scope.globalContent, "name_col_lbl")['value]' ***This is where I need to search for the string and return its value***;
$scope.bdayLbl= findObject($scope.globalContent, "bday_col_lbl")['value]' ***This is where I need to search for the string and return its value***;
});
The findObject function filters the array by returning the first object that it finds where obj.item matches whatever is contained in keyName. This is the obj object which gets returned. Since you don't want the whole object but just a value of that object, I've taken the result of the findObject($scope.globalContent, "name_col_lbl") and added ['value'] which will return just the value key which is what you want to display in the Angular view.
I'm trying to restructure an object for convience.
This is the general structure:
var dictionary = { "word": {"content": "wordy"}, "palabra": {"content":"palabrota" }};
I want it to look like this:
[{"wordy":"word"},{"palabrota":"palabra"}]
And I'm trying this code out:
_.map(dictionary, function(v,k){ var new_key = v.content;return { new_key: k };} );
But instead of what I am expecting, this is the result:
[ { new_key: 'word' }, { new_key: 'palabra' } ]
How to get a key to be used as a variable in this function?
You can use the _.invertBy method (as of LoDash v4.1.0), which will give you the key and an array of the values, thus ensuring the values aren't overwritten.
var dictionary = {
"word": {"content": "wordy"},
"anotherWord": {"content": "wordy"},
"palabra": {"content":"palabrota" }
};
var result = _.invertBy(dictionary, function(item) {
return item.content;
});
// "{"wordy":["word","anotherWord"],"palabrota":["palabra"]}"
EDIT: earlier response below. This works, however the limitation is duplicate content values would overwrite the keys. The docs for _.transform below shows how to generate an array to handle duplicates, and a similar setup can be used for the regular JS approach.
You can use the _.transform method:
var transformedResult = _.transform(dictionary, function(result, value, key) {
return result[value.content] = key;
});
Or without LoDash at all, you can construct the object as intended.
var result = {};
Object.keys(dictionary).forEach(function(key) {
var value = dictionary[key].content;
result[value] = key;
});
I might recommend _.mapValues(dictionary, "content") for simplicity.
However, instead of [{"wordy":"word"},{"palabrota":"palabra"}], instead you'll get {"wordy": "word", "palabrota": "palabra"} as the result from _.mapValues. But given that you're using lodash, and lodash treats arrays and objects pretty much interchangeably, I think the non-array version would be more convenient.
what I am really trying to do is add an array after an event only if that event occurred once like the press of the enter button. if the user keeps on entering the wrong answer it should only update the array once with the array that represents the question. if you can help me out with this question that deals with more of what i am trying to do would be great.
if you cant help me with that i am wondering how to insert an array after an event only if the array isn't in the array. can you show me some code where you search for an array inside of an array and if that array is inside do something or nothing?
I don't understand why in the below code i am not able to search for arrays
function onlyUnique(value, index ,self){
return self.indexOf(value) === index;
}
var a = ['a' , [1], [1],'a']
var unique = a.filter(onlyUnique)
console.log(unique)
You could use an object like an associative array. You would need some way to identify the questions to link to the answers.
// answers storage
var answers = {};
// set answer to question 1, this would be replaced by automation
var questionId = 'q1';
var data = 'some answer';
// insert if not present
if(answers[questionId] === undefined) {
answers[questionId] = data;
}
// manipulate existing answer
else {
// do something with answers[questionId]
}
There is not a simple operation to do a deep comparison of objects. However, you can try converting the objects to JSON and comparing - provided the JSON generated has the objects properties in the same order then it will generate identical strings which can be compared:
function onlyUnique(a){
return a.map(function(v){ return JSON.stringify(v); })
.sort()
.filter(function(v,i,a){ return i==0 || v !== a[i-1]; })
.map(function(v){return JSON.parse(v);});
};
var a = ['a' , [1], [1],'a']
var unique = onlyUnique(a);
console.log(unique)
I am just curious about this.
Let's say I have an array of objects and I create 1 object, lets name the array of objects items and the object item.
I want to get a particular item in my array of items by using the following code:
//gets an item base on ID
function get_item(td){
var item = undefined;
$.each(items, function(i, val) {
if(val.item_id == td){
item = val;
}
});
return item;
}
The get_item() basically gets an object matched with the supplied id.
So my question is this. What if I changed the properties of item will it also changed the properties of an object associated with it within the array?
Thank you very much!
What if I changed the properties of item will it also changed the properties of an object associated with it within the array?
Yes.
Objects are not copied. Instead, references to the objects are passed around. Simplest example:
var a = [];
var b = a;
b.push(1);
console.log(a); // logs [1]
Many object-oriented programming languages work like this.
The value of the object inside the array will also change because it's a reference. If you want more information I highly recommend reading Objects and Prototypes.
If you don't want it to change then you should use something like lodash's _.clone() function.
Also you could use filter to get the object:
function get_item(td){
return items.filter(function(item) {
return item.id === td;
})[0];
}
You can update you function to:
var data= array();
function get_item(propertyValue, propertyName){
var retval;
for(var i = 0; i < data.length; i++){
if(data[i][propertyName]==propertyValue){
retval = data[i];
break;
}
}
return retval;
}
Use it
var item1 = get_item(1,"id");
var item2 = get_item("john","name");