Array cannot access elements? - javascript

I am playing with the amazon alexa skills and trying to write my own. I have an array for some elements of the skill, but I cannot access the elements. I believe I've done everything correctly and I've googled a fair bit, but nothing seems to be working?!
var myArray = [
{ "name" : "matt", "content" : "this is about matt" },
{ "name" : "james", "content" : "this is about james" },
];
I then have some code based on the user input which uses the name as a finder.
var requestedName = "matt";
var contentToRead = myArray.filter(function(v){ return v.name == requestedName; });
console.log("I'll read back, " + contentToRead.content);
The above console.log is coming back as undefined. I've tried to parse the results to an array, but nothing I try seems to work.
any ideas? I am sure it's something simple, but my knowledge isn't enough to actually know what specifically to look for to solve it!!

.filter filters the array, it removes values not matching the filter; what you'll get back is still an array with multiple objects (because the predicate may apply to more than one value in the array).
The behaviour you want, returning the first match, is implemented in .find:
var contentToRead = myArray.find(function (v) { return v.name == requestedName; });

Array.prototype.filter() creates a new array with all elements that pass the test implemented by the given function, so contentToRead is an array:
var myArray = [
{ "name" : "matt", "content" : "this is about matt" },
{ "name" : "james", "content" : "this is about james" },
];
var requestedName = "matt";
var contentToRead = myArray.filter(function(v) { return v.name === requestedName; });
// You can loop over contentToRead array
contentToRead.forEach(function(item) {
console.log("I'll read back, " + item.content);
});

filter creates a new array containing the elements for which the function you pass it returns true.
content isn't a property of the array, it is a property of each object inside that array.
You would need need to get elements out of the array to read their content.
contentToRead.forEach(function (currentValue) {
console.log("I'll read back, " + currentValue.content);
});

The value returned by myArray.filter(function(v){ return v.name == requestedName; });is an array containing the object matching your filter.
As you only have one object in it, you could access it like :
contentToRead[0].name

Related

Get key values in JSON array

I'm trying to get the key values of each record in a JSON array when looping through it. Currently I have a simple JSON object like this:
"users": {
"key_11": {
"text": "11"
},
"key_22": {
"text": "22"
},
"key_33": {
"text": "33"
}
}
My current script uses the 'map' method to convert this JSON objet to a loop-able array:
var user_profiles_array = $.map(user_profiles_string, function(el) { return el; });
for (var xt = 0; xt < user_profiles_array.length; xt++) {
console.log(user_profiles_array[xt].text); //11 or 22
}
My question is, how can I get the value for e.g: 'key_11' or 'key_22'?
Thanks!
you can use Object.keys to get an array of all of your object's keys. Once you have that array, you can use Array.forEach to iterate over it as necessary:
Object.keys(usersObject).forEach(function(key, keyIndex) {
console.log("index:",keyIndex,"key:",key,"value:",usersObject[key]);
});
But!
your particular problem here is being caused by using $.map instead of JSON.parse. $.map returns an array, so of course your keys are always going to be numerical array indices - 0, 1, 2, and so on. You're not going to be able to use hash keys to find things in the array returned by $.map. Furthermore, judging by your variable names you're calling $.map on a string which is definitely not going to do what you want. Assuming you figure that part out and you somehow get a valid JavaScript object, and you still need to use $.map() for some reason, what you can do is this:
// $.map will return an array...
$.map(user_profiles_object, function(objVal, objKey) {
// ...and each item in that array will be an object with a
// property named 'key' and a property named 'val'
return {
key: objKey,
val: objVal
};
}).forEach(function(arrayObj) {
// now each item in the array created above will be an object
// created by your callback function:
console.log(arrayObj.key,":",arrayObj.val);
});
You can also rely on Js's foreach.
// JSON string must be valid. Enclose your JSON in '{}' (curly braces);
var user_profiles_string = '{ "users": { "key_11": { "text": "11" }, "key_22": { "text": "22" }, "key_33": { "text": "33" }}}';
var user_profiles_array = JSON.parse(user_profiles_string);
// For retrieval in loop, the Js foreach asigns the key to index param (i in this case).
for (i in user_profiles_array.users) {
// i is the key of the user currently iterated.
console.log('Key name is: ' + i);
// Use i as the index to retrieve array value.
console.log(user_profiles_array.users[i]);
}
// For direct retrieval using any given known key:
console.log(user_profiles_array.users['key_11']);

array.sort not working on array of objects

I got the following object array:
var arr = [{
2: {
1: { name: "test" },
2: { name: "apple" }
},
3: {
1: { name: "banana" },
2: { name: "pear" }
}
}];
Just some sample data. Now, I got 3 textareas:
<textarea id="first"></textarea>
<textarea id="second"></textarea>
<textarea id="third"></textarea>
And I have the following custom-made function:
function sort(alt)
{
arr.sort(function (a,b)
{
console.log(a);
if (a[2].name < a[2].name)
return (alt) ? 1 : -1;
if (a[2].name > a[2].name)
return (alt) ? -1 : 1;
return 0;
});
}
It should sort the array of objects by name, ascending or descending according to parameter. Now, I got 2 problems. This way I append all the values to the textareas:
for (var key in arr[0])
{
var obj = arr[0][key];
$(ID).append(obj[2].name + '\n');
}
The first time, that code will be executed without running sort. The second time, sort will be executed with false as parameter, than that code will be executed. The third time sort will be executed with true as parameter, than that code will be executed. However, the output of all textboxes is exactly the same.
This is a link to the jsfiddle:
http://jsfiddle.net/JoshB1997/gow4vzsc/
Also, the console.log(a) doesn't get printed in the console.
So variable arr is an array but as far as I can see it contains only one object.
You're trying to sort directly onto the array, since it only has one object it will simply never sort because there is nothing to sort.
You'll want to access arr[0] which is the object containing the actual objects you want to sort however the Object prototype doesn't contain any of the array functions so you cannot call sort on it even tho technically an Array is an Object an Array inherits from Object and not the other way around so the methods from Object are available to Array but not the other way around.
Also, you're trying to compare the same a[2].name with itself so it'll always be false since it's equal, not > or <.
In your case I extract all the name properties from every nested object you have like this (considering the usage of the original arr):
var compare = [];
var alt = false;
for (k in arr[0]) {
if (arr[0].hasOwnProperty(k)) {
for (l in arr[0][k])
if (arr[0][k].hasOwnProperty(l))
compare.push(arr[0][k][l].name);
compare.sort(function(a, b) {
if (a == b)
return 0;
else if (a < b)
return alt ? 1 : -1
else
return alt ? -1 : 1
});
Now you can use the compare array to output the sorted names correctly.
Also - your construction seems overly complex? It has objects and within them are nested objects but you're only sorting and displaying names, is there any reason this structure has to be maintained?
If not I would highly recommend you simplify this to just be an array of names, the loop I made above is far from beautiful and I'd rather have you not use it since it assumes that the outmost object is an object filled with other objects that all have the name property. This code could still break without an extra arr[0][k][l].hasOwnProperty('name').
Either way, the compare array simply contains all the names and it easily sortable with the default sort if you don't make things to complex for yourself.
I suggest you to use http://underscorejs.org/ that contains quite really useful function to transform from object to arrays.
For example in this case you can use something like http://underscorejs.org/#values
let values = _.values(arr[0]);
Now values is an array that contains your two object (2,3) in the form
values = [
{
1: {
name: "test"
},
2: {
name: "apple"
}
},
{
1: {
name: "banana"
},
2: {
name: "pear"
}
}
]
and here you can call your sort function
There is my demo on your code with underscore.js http://jsfiddle.net/gow4vzsc/3/
EDIT: If you cant/wont to include an entire library you can write your code for get the values:
values = [];
for(key in arr[0]){
values.push(arr[0][key]);
}
Here a demo without underscore.js http://jsfiddle.net/3L7ttu2r/1/

Check if an object has a key in javascript

I have two arrays of objects, and I want to filter the first one according to whats on the second one. Here's an example:
var ary1 = [{id: 23, title: 'blabla'},{id:43, title: 'bleble'}, {id:54, title:'blibli'}];
var ary2 = [{id:23},{id:54}, {id:65}];
So in this case what I want to return is an array with the objects that have id's 23 and 54 of the first array, with all its possible properties (in this case, title).
Could you give me any hint that could help me?
Get a list of the indexes you want to search on using map:
var indexes = ary2.map(function (el) {
return el.id;
});
filter the results based on the list of indexes:
var result = ary1.filter(function (el) {
return indexes.indexOf(el.id) > -1;
});
DEMO
This might help you.
Loop through ary2, building up an array of each id value (let's call this array existingIds).
After that loop, now loop through ary1. For each item in ary1, check to see if the id value exists in the existingIds array that we just built up. If it does, append the current item to a result array.
I could write the code for you, but it will be a better learning experience if you first try this yourself :)
Might as well make use of some functional programming built into javascript.
filteredResults = ary1.filter(function(ele){
return (ary2.map(function(idobj){return idobj.id;}).indexOf(ele.id)>-1)
})
filter(function) will iterate through each element of an array, passing it through a callback function. From within that callback iff a true is returned, that value is kept. If false, that value is filtered out.
Also map(function) will iterate through each element of an array passing a callback value as well. All values returned from map callback will be injected into the result. So we can take the id from each element in ary2 and return it in the map function.
var ary1 = [{id: 23, title: 'blabla'},{id:43, title: 'bleble'}, {id:54, title:'blibli'}];
var ary2 = [{id:23},{id:54}, {id:65}];
//Filter for the available ID's, store the resulting objects in a new array
filteredResults = ary1.filter(function(ele){
//map creates an array of just ID's
return (ary2.map(function(idobj){return idobj.id;}).indexOf(ele.id)>-1)
})
//now do whatever you were planning on doing with your results/
var res = document.getElementById("results");
filteredResults.forEach(function(ele){
res.innerHTML+="<li>{id:"+ele.id + ",title:" +ele.title+"}</li>"
})
console.log(filteredResults);
<ul id="results"></ul>
try this:
var ary1 = [{id: 23, title: 'blabla'},{id:43, title: 'bleble'}, {id:54, title:'blibli'}];
var ary2 = [{id:23},{id:54}, {id:65}];
var newary=[];
for(x in ary1){
for(y in ary2){
if(ary1[x].id == ary2[y].id){
newary.push(ary1[x]);
}
}
}
console.log(newary);// here newary will be your return newary;

Underscore.js, get two items from an object and add to the top

I have an object that looks like this
{
"AF" : {
"name" : "Afghanistan"
},
"AL" : {
"name" : "Albania"
}
}
It has objects for all countries.
What I would like to do is copy the objects from certain ISO's and add them to the top of the object (without removing the original).
What I started to do is this:
var filtered = _.collect(data, function(item, key){
if($.inArray(item.iso, ['US','CA']) !== -1) {
return item;
}
});
This gives me an array, with the objects. But, how would I add these to the original object?
Thank you!
As #mu-is-too-short said, JS objects have no mandatory ordering of their properties.
Also, your objects' properties don't have an iso property, which you're depending upon.
Please edit your question once you've seen that :)
If your code is depending on that, you're going the wrong way. As he suggests, you should use an array instead, but you can keep the objects inside of it. I'll suppose you start with a structure of the object literal shown first in your question. With this snippet, you'll be creating an array with the default order, and then adding the filtered objects to the head of that array:
var data = {
"AF" : {
"name" : "Afghanistan"
},
"AL" : {
"name" : "Albania"
}
};
var countries = _.collect(data, _.identity);
var repeated = [];
_.forEach(countries, function(country) {
if (repeatsAtTheTop(country)) {
// Added in reverse order so it preserves the
// original once unshifted into the original array
repeated.unshift(country);
}
});
_.forEach(repeated, function(item, index) { countries.unshift(item) });

jQuery.map - Practical uses for the function?

I am trying to get a better understanding of the jQuery.map function.
So in general terms .map takes a array and "maps" it to another array of items.
easy example:
$.map([0,1,2], function(n){
return n+4;
});
results in [4,5,6]
I think I understand what it does. I want to under why would someone need it. What is the practical use of this function? How are you using this in your code?
Mapping has two main purposes: grabbing properties from an array of items, and converting each item into something else.
Suppose you have an array of objects representing users:
var users = [
{ id: 1, name: "RedWolves" },
{ id: 2, name: "Ron DeVera" },
{ id: 3, name: "Jon Skeet" }
];
Mapping is a convenient way to grab a certain property from each item. For instance, you can convert it into an array of user IDs:
var userIds = $.map(users, function(u) { return u.id; });
As another example, say you have a collection of elements:
var ths = $('table tr th');
If you want to store the contents of those table headers for later use, you can get an array of their HTML contents:
var contents = $.map(ths, function(th) { return th.html(); });
$.map is all about converting items in a set.
As far as the DOM, I often use it to quickly pluck out values from my elements:
var usernames = $('#user-list li label').map(function() {
return this.innerHTML;
})
The above converts the <label> elements inside a list of users to just the text contained therein. Then I can do:
alert('The following users are still logged in: ' + usernames.join(', '));
Map is a high-order function, that enables you to apply certain function to a given sequence, generating a new resulting sequence containing the values of each original element with the value of the applied function.
I often use it to get a valid selector of all my jQuery UI panels for example:
var myPanels = $('a').map(function() {
return this.hash || null;
}).get().join(',');
That will return a comma separated string of the panels available in the current page like this:
"#home,#publish,#request,#contact"
And that is a valid selector that can be used:
$(myPanels);// do something with all the panels
Example:
$.map($.parseJSON(response), function(item) {
return { value: item.tagName, data: item.id };
})
Here server will be returning the "response" in JSON format, by using $.parseJSON it is converting JSON object to Javascript Object array.
By using $.map for each object value it will call the function(item) to display the result value: item.tagName, data: item.id
Here's one thing you could use it for.
$.map(["item1","item2","item3"], function(n){
var li = document.createElement ( 'li' );
li.innerHTML = n;
ul.appendChild ( li );
return li;
});
Recently I discovered an excellent example of .map in a practical setting.
Given the question of How to append options to a selectbox given this array (or another array):
selectValues = { "1": "test 1", "2": "test 2" };
this StackOverflow answer uses .map:
$("mySelect").append(
$.map(selectValues, function(v,k) {
return $("<option>").val(k).text(v);
})
);
Converting code values to code text would be a possible use. Such as when you have a select list and each indexed value has a corresponding code text.

Categories

Resources