I want to map the keys of a large array into another key while removing the original key using Underscore.js' map() function.
large_array = _.map(data, function(element) {
element.b = element.a;
delete element.a;
return element;
});
console.log(large_array) // Returns an array with length == 0
Why would large_array have a length of zero?
I feel like I'm using the delete statement incorrrectly but I'm not sure.
Edit:
I may be abstracting this code too much, since simple runs seem to be working just fine.
The original data array is response from the FB.api('/me/friends', function(response) {...}
More specifically, it is an array of objects such as
{id: "12345", name: "Bubba Watson"}
As this is a response from Facebook, each object is guaranteed to have the 'id' attribute
The actual code is changing the the 'id' property to a 'facebook_id' property.
FB.api('/me/friends', function(response) {
console.log(response.data); // Returns 600+ Array of Bubba Watson like objects, each with an id.
large_array = _.map(response.data, function(element) {
element.facebook_id = element.id;
delete element.id;
return element;
});
console.log(large_array); // Mysteriously Returns: {length: 0, __proto__: Array[0]}
}
You're using delete correctly, however you may need to make sure:
data is indeed type Array and there are elements in data array
each element in the data array has property named a
Your code works for me: http://jsfiddle.net/EJTgx/
var data = [
{ a: 10 },
{ a: 20 },
{ a: 30 }
];
var large_array = _.map(data, function(element) {
element.b = element.a;
delete element.a;
return element;
});
console.log(large_array.length); // Returns 3
Related
I have an array, inside this I have objects. I need to work with this and need to access to the object data.
Here is a sample of this array:
var result <-
(16)array […]
0:object {…}"myobjectname1": {…} style_name: "border-top-right-radius"
style_unit: "px"
style_value: "0"
1:object {…}"myobjectname2": {…} style_name: "border-bottom-right-radius"
style_unit: "px"
style_value: "0"
2:object { "myobjectname3": {…} }
3:object { "myobjectname4": {…} }
4:object { "myobjectname5": {…} }
...
I want to access directly to the different objects by the objectname
Example alert("result.myobjectname1.style_name");
It seem that this could not work, because I don't access the array by the index in this case [0]!?
I don't know this index, it could be different every time.
Is there a way, to directly access the objects by the objectname or in which way, I have to create a array/object that it works?
In php I will do it with a simple array, in JavaScript its not possible because my index is alphanumeric.
UPDATE
This is the way i create the datas in a each-loop
var match=new Array();
each(...)
{
...
var r = null;
r={ [myobjectname_from_variable] : { 'style_name': res_stylename,
'style_value': res_stylevalue,
'style_unit' : elem_styleunit} };
match.push(r);
...
}
Important: The value of myobjectname_from_variable is the same as res_stylename and it contains something like "border-top-right-radius"
Here we have to think about, how i can call this in javascript. For example
object.border-top-right-radius.style_value
wont breack and returns a error of undefined "right"...
You could build an object with all objects of the array. Then take the key of the wanted object for access.
var array = [
{ foo: { id: 1, name: 'foo' } },
{ bar: { id: 2, name: 'bar' } },
{ baz: { id: 3, name: 'baz' } }
],
object = Object.assign(...array);
console.log(object.foo.id);
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For a faster access via a key, you could build your object with a defined object, like
var data = {};
And in the loop, you could assign the value object like this with a property accessor
// inside of the loop
data[myobjectname_from_variable] = {
style_name: res_stylename,
style_value: res_stylevalue,
style_unit: elem_styleunit
};
Your best bet is to iterate the array and then call the index of each iteration. There's also an array method called .forEach that wraps this up for you.
var yourArray = []; // contains the array of objects you mentioned
yourArray.forEach(object => {
const key = Object.keys(object)[0];
alert(object[key].style_name);
})
Update
Your main issue is the use of hyphens in your keys. If you want to index an object like that then you'll need to reference the keys as strings.
const obj = {'border-top-right-radius':'style_value'};
const test = obj['border-top-right-radius'];
console.log(test); // this logs 'style_value '
const other = obj.border-top-right-radius;
// This will throw that 'right' is undefined.
If you want that format then change your hyphens to underscores. With underscores, there's no issue directly referencing them as you desire. You can easily remap to the hyphenated string later for what you're doing with .replace
const underscoreReplacement = 'border_top_right_radius';
const actualSheetValue = underscoreReplacementreplace(/_/g, '-');
console.log(actualSheetValue); // logs 'border-top-right-radius'
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']);
EDIT : Included more details
Hi I have a Object Array in jQuery which looks like this,
My question is how can I delete a record from that object array by columnheader as parameter. I know there is this
var result = $.grep(records, function(e){ return e.columnheader == currentheader; });
but grep i only used to check if there's a matching data based on currentheader that i passed in. What if I want to delete?
I want to delete a record on the fly as I am looping in that object array, lets I have. data contains all object arrays that is shown in the image.
$.each(data, function(key,value) {
// Let's say I want the code here to delete a record in the current object array that I'm looping into.
});
Thanks
You can use filter()
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
arr = arr.filter(function(e) {
return e.columnheader !== currentheader;
});
Demo
var arr = [{
name: 'John Skeet',
rank: 1
}, {
name: 'T.J.Crowder',
rank: 10
}];
console.log(arr);
arr = arr.filter(function(e) {
return e.rank !== 10
});
console.log(arr);
UPDATE
I want the code here to delete a record in the current object array that I'm looping into
Changing a property from object in array.
var arr = [{
name: 'John Skeet',
rank: 1
}, {
name: 'T.J.Crowder',
rank: 10
}];
$.each(arr, function(index, obj) {
if (obj.rank === 10) {
arr[index].rank = 9;
}
});
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
You can use the JavaScript splice method to do it. First find the index of your object in the array then use the method like that :
your_array.splice(obj_index,0);
EDIT
The easy way but not optimized is to use a for loop to get the index, a better solution is to use linq.js to get the object, then your_array.indexOf(your_obj);
EDIT 2
You can download linq.js here Linq.js
You can use it like this:
function DelteObjFromArray(your_value){
var objToDelete = Enumerable.From(your_array).Where(function (x) { return x.your_property == your_value; }).FirstOrDefault();
var objIndex = your_array.indexOf(objToDelete);
your_array.splice(objIndex,1);
}
So, essentially I am getting a set of records as an array of objects like
[{name: tyler, categories: ["friends", "neighbor"]}, {name: joe, categories: ["friends"]}].
and I want to count the contents of the internal array instances. So in this example, the return would be friends: 2 and neighbor: 1. As some background info, I am getting a collection of records from mongo within the meteor framework. I am then using fetch() to convert these records to an array of objects like above. I then want to use these objects to create a pie graph based on the counts of the specific instances of each object within the inner array of each object (these objects would be the ones returned by the db query) within the outer array.
You can write a simple function to count your categories counts and store the result in a dictionary of key/value pairs.
function countCategories(docs){
// accumulate results inside a JS object acting as a key/value dict
var result = {};
docs.forEach(function(doc){
doc.categories.forEach(function(category){
// initialize count to 0 when a new key is found
if(_.isUndefined(result[category])){
result[category] = 0;
}
// increment the corresponding count
result[category]++;
});
});
return result;
}
Given the sample data in your question, this function will return :
Object {friends: 2, neighbor: 1}
EDIT :
You can then convert this dictionary to an array of objects.
function convertToArray(dict){
var result = [];
_.each(dict, function(value, key){
var object = {
category: key,
count: value
};
result.push(object);
});
return result;
}
Using underscore and reduce:
result = _.reduce( data, function( counter, o ) {
_.each( o.categories, function(c){
counter[c] = 1 + _.result(counter, c, 0);
});
return counter;
}, {});
Demo in this fiddle
reduce goes through your array (first arg) and applies
the function you give it (second arg) and a starting value for
the memo (third arg). This memo is passed to each call to
your function as the first argument, you can us it to store
stuff you want to remember.
I've set the starting value for the memo to be an empty object
which we will use as a counter.
result = _.reduce( data, function( counter, o ) {
// current element of the array: o
// stuff you want to remember for: counter
return counter;
}, {});
You might attach a function to the array and count the elements inside of it.
yourArray = [1,2,3];
yourArray.countElements = function(){
var elements=0;
for(x=0;this[x]!=undefined;x++){
instances++
}
return instances;
};
yourArray.countElements(); // outputs 3
Modify this, using "neighbors" and "friends" instead of "elements" and counting them only if this["categories"]["the_category"] is different of undefined.
Also you could attach it to Array.prototype
I currently have a problem in deleting entries from an associative array in JS.
I tried this:
myArray['key'] = value;
myArray['key1'] = value1;
...
delete myArray['key'];
But I get following results in my application:
[ undefined, { key1: 'value1', key2: 'value2' }, undefined,
{ key1: 'value1', key2: 'value2' }, undefined, undefined ]
How can I delete the whole entry, key and value? I found the method splice() but I think it uses a different index. I wasn't able to delete the entries I want by passing the key to splice().
It seems you are mixing arrays and objects. Associative arrays should be realized with objects:
myArray = {};
myArray['key'] = value;
myArray['key1'] = value1;
It is a bit confusing though because in your output, the objects don't have key anymore (so it worked), but the array containing those objects as undefined values. I cannot see how
delete myArray['key']; is related to your output and which variable now contains which value (please clarify).
But it looks like you did something like:
var container = new Array(6);
container[1] = myArray;
container[3] = myArray;
This will initialize the array with 6 undefined values (sort of) and then set the second and forth value to something else.
If you want to use that "array" as associative array, you should declare it as object too:
var container = {};
Please post more code if you need a better answer.
Update: Yes, you should declare displayedWidgets as object:
var widgets = {
displayedWidgets: {},
clear: function() {
this.displayedWidgets = {};
},
add: function(widget) {
this.displayedWidgets[widget.id] = widget;
},
addArray: function(newWidgets) {
// note that `each` is only available in newer browsers,
// just loop over the array
for(var i = newWidgets.length; i--; ) {
this.add(newWidgets[i]);
}
},
remove: function(widgetId) {
if (widgetId in this.displayedWidgets) {
delete this.displayedWidgets[widgetId];
}
}
};