AngularJS select array hash element by name/value - javascript

I have the following angular array for one of my select tags
var names= [{name: 'Superman', val: '1'}, {name: 'Batman', val: '2'}];
$scope.names =names;
$scope.FormData = {};
$scope.FormData.name = $scope.names[1];
In the above array, instead of selecting the item by index (1), how can I select the item by name or the val, like
$scope.FormData.name = $scope.names['2']; #will select the {name: 'Batman', val: '2'}
I initially posted a lengthy question here, but then I realized this is the more simpler / focus way of my question

If you are using angular, why not use the build in $filter?
https://docs.angularjs.org/api/ng/filter/filter
In your case, if you want to filter in the controller, the code bellow will retrieve an Array with all the occurrences inside names that match the search for 'Superman':
$filter('filter')($scope.names, {name:'Superman'})
If you are confident that there will be at least one match you could do this in order to get the first match:
var matches = $filter('filter')($scope.names, {name:'Superman'});
var match = matches[0]:
Bare in mind that if there are no matches then match will be undefined

If you want a re-useable function you could do it like this:
$scope.find = function(list, attributeName, attributeValue){
var returnVal = {};
angular.forEach(list,function(item){
if(item[attributeName]){
if(item[attributeName] === attributeValue){
returnVal = item;
}
}
});
return returnVal;
};
$scope.FormData.name = $scope.find(names,'name','Batman');

In the above array, instead of selecting the item by index (1), how
can I select the item by name
You can use the find method of the Lodash library (http://lodash.com/docs#find):
var names= [{name: 'Superman', val: '1'}, {name: 'Batman', val: '2'}];
var matchingBatman = _.find(names, { name: 'Batman' });
matchingBatman is: {name: 'Batman', val: '2'}
You can do the same if you want to find by val:
var matchingBatman = _.find(names, { val: '2' });

If you want to write a function instead of using a library
function selectByProperty(key, val){
for(var i=0; i< $scope.names.length; i++){
if($scope.names[i][key] === val){
return $scope.names[i];
}
}
}
$scope.FormData.name = selectByProperty('val','2');

Related

live filter using underscorejs with an array of objects?

I am trying to filter an array depending on the name attribute typed.
var data = [
{name: "Google"},
{name: "Yahoo"}
];
var search = function(letters){
var pattern = new RegExp(letters,"gi");
_.filter(function(data) {
return pattern.test(data.get("name"));
});
};
search("yah"); // should return {name: "Yahoo"}
this is not working for me.
_.filter needs a first argument, here being your array data and applies a callback on each element of data, I think it could look like this:
search = function(letters){
var pattern = new RegExp(letters,"gi");
return _.filter(data, function(object) {
return pattern.test(object.name);
});
};

Matchmaking Array, Javascript

I'm trying to make a javascript key-value array with the key as the name of the person and the value as a numerical one indicating their compatibility (1 lowest, 10 highest). Something like this :
var array = [ {name: "Sean", value: 7},
{name: "Sarah", value: 8},
{name: "Chloe", value: 5} ];
However I want to create the array somewhat dynamically, where two separate arrays- one of names and one of numbers - would make up the key-values. How would I go about doing this?
simply by specifying the names as key and the corresponding values as value
var ar = {};
var name = 'xyz';
var value = 1;
ar[name] = value;
Try this syntax:
var array = {"Sean":7,"Sarah":8,"Chloe":5};
And if you want to add the items one by one:
var array = {};
array["Sean"] = 7;
array["Sarah"] = 8;
array["Chloe"] = 5;

Create two arrays from a collection of object property and values with lodash

I have an array that contains objects, like this:
[{
"first" : 1
},
{
"second" : 2
},
{
"third" : 3
}]
I want to turn this into two arrays, with indexes matching based on these values, such as:
["first","second","third"]
[1,2,3]
I can iterate through this and get the object keys and values, but I feel there's gotta be a slick way in lodash to do this, that I don't know of. Any suggestions? Thank you!
It seems like you just need to map over the object and call keys() and values()
You will get the first array like:
var items = [{a: "1"},{b: "blah",c: "what"},{d: "3"}]
keys = _(items).map(_.keys).flatten().value()
returns ["a","b","c","d"]
And the second array like:
values = _(items).map(_.values).flatten().value()
returns ["1","blah","what","3"]
For a non-lodash solution:
var arr = [{"first" : 1},{"second" : 2},{"third" : 3}];
var keys = arr.map(function(el){return Object.keys(el)[0];});
var vals = arr.map(function(el){return el[Object.keys(el)[0]];});
For the opposite problem (multiple arrays into one array of objects), see Merge two arrays into an array of objects with property values
Assuming that your object shape is always {"label": value}, then you can use this vanilla JavaScript:
var data = [{"first" : 1},{"second" : 2},{"third" : 3}];
var labels = data.map(function(entry) {
return Object.keys(entry)[0];
});
var values = data.map(function(entry) {
return entry[Object.keys(entry)[0]];
});
Your data structure seems sub-optimal based on your comments. I would recommend an alternate structure:
var data = [
{'label': 'first', 'value': 1},
{'label': 'second', 'value': 2},
{'label': 'third', 'value': 3}
]
Which is then trivial to pick out the labels and values into separate pieces in normal JavaScript:
var labels = data.map(function(entry) {
return entry.label;
});
var values = data.map(function(entry) {
return entry.value;
});
Or if you really want to use lodash:
var labels = _.pluck(data, 'label');
var values = _.pluck(data, 'value');
Hopefully you can see that this revised structure makes the JavaScript much simpler whether you use lodash or not.

Adding elements to object

I need to populate a json file, now I have something like this:
{"element":{"id":10,"quantity":1}}
And I need to add another "element". My first step is putting that json in a Object type using cart = JSON.parse, now I need to add the new element.
I supposed I must use cart.push to add another element, I tried this:
var element = {};
element.push({ id: id, quantity: quantity });
cart.push(element);
But I got error "Object has no method push" when I try to do element.push, and I think I'm doing something VERY wrong because I'm not telling the "element" anywhere.
How can I do that?
Edit: sorry to all I had a LOT of confusion in my head.
I thought I can get only object type when taking data from JSON.parse, but I get what I put in the JSON in the first place.
Putting array instead of object solved my problem, I used lots of suggestions got here too, thank you all!
Your element is not an array, however your cart needs to be an array in order to support many element objects. Code example:
var element = {}, cart = [];
element.id = id;
element.quantity = quantity;
cart.push(element);
If you want cart to be an array of objects in the form { element: { id: 10, quantity: 1} } then perform:
var element = {}, cart = [];
element.id = id;
element.quantity = quantity;
cart.push({element: element});
JSON.stringify() was mentioned as a concern in the comment:
>> JSON.stringify([{a: 1}, {a: 2}])
"[{"a":1},{"a":2}]"
The line of code below defines element as a plain object.
let element = {}
This type of JavaScript object with {} around it has no push() method. To add new items to an object like this, use this syntax:
element[yourKey] = yourValue
To put it all together, see the example below:
let element = {} // make an empty object
/* --- Add Things To The Object --- */
element['active'] = true // 'active' is the key, and 'true' is the value
console.log(element) // Expected result -> {type: true}
element['state'] = 'slow' // 'state' is the key and 'slow' is the value
console.log(element) // Expected result -> {type: true, state: 'slow'}
On the other hand, if you defined the object as an array (i.e. using [] instead of {}), then you can add new elements using the push() method.
To append to an object use Object.assign
var ElementList ={}
function addElement (ElementList, element) {
let newList = Object.assign(ElementList, element)
return newList
}
console.log(ElementList)
Output:
{"element":{"id":10,"quantity":1},"element":{"id":11,"quantity":2}}
If the cart has to be stored as an object and not array (Although I would recommend storing as an []) you can always change the structure to use the ID as the key:
var element = { quantity: quantity };
cart[id] = element;
This allows you to add multiple items to the cart like so:
cart["1"] = { quantity: 5};
cart["2"] = { quantity: 10};
// Cart is now:
// { "1": { quantity: 5 }, "2": { quantity: 10 } }
Adding new key/pair elements into the original object:
const obj = { a:1, b:2 }
const add = { c:3, d:4, e: ['x','y','z'] }
Object.entries(add).forEach(([key,value]) => { obj[key] = value })
obj new value:
{a: 1, b: 2, c: 3, d: 4, e: ['x', 'y', 'z'] }
I was reading something related to this try if it is useful.
1.Define a push function inside a object.
let obj={push:function push(element){ [].push.call(this,element)}};
Now you can push elements like an array
obj.push(1)
obj.push({a:1})
obj.push([1,2,3])
This will produce this object
obj={
0: 1
1: {a: 1}
2: (3) [1, 2, 3]
length: 3
}
Notice the elements are added with indexes and also see that there is a new length property added to the object.This will be useful to find the length of the object too.This works because of the generic nature of push() function
you should write var element = [];
in javascript {} is an empty object and [] is an empty array.
cart.push({"element":{ id: id, quantity: quantity }});
function addValueInObject(object, key, value) {
var res = {};
var textObject = JSON.stringify(object);
if (textObject === '{}') {
res = JSON.parse('{"' + key + '":"' + value + '"}');
} else {
res = JSON.parse('{' + textObject.substring(1, textObject.length - 1) + ',"' + key + '":"' + value + '"}');
}
return res;
}
this code is worked.
Try this:
var data = [{field:"Data",type:"date"}, {field:"Numero",type:"number"}];
var columns = {};
var index = 0;
$.each(data, function() {
columns[index] = {
field : this.field,
type : this.type
};
index++;
});
console.log(columns);
If anyone comes looking to create a similar JSON, just without using cart as an array, here goes:
I have an array of objects myArr as:
var myArr = [{resourceType:"myRT",
id: 1,
value:"ha"},
{resourceType:"myRT",
id: 2,
value:"he"},
{resourceType:"myRT",
id: 3,
value:"Li"}];
and I will attempt to create a JSON with the following structure:
{
"1":{"resourceType":"myRT","id":"1","value":"ha"},
"2":{"resourceType":"myRT","id":"2","value":"he"},
"3":{"resourceType":"myRT","id":"3","value":"Li"}
}
you can simply do-
var cart = {};
myArr.map(function(myObj){
cart[myObj.id]= myObj;
});
function addValueInObject(value, object, key) {
var addMoreOptions = eval('{"' + key + '":' + value + '}');
if(addMoreOptions != null) {
var textObject = JSON.stringify(object);
textObject = textObject.substring(1,textObject.length-1);
var AddElement = JSON.stringify(addMoreOptions);
object = eval('{' + textObject +','+ AddElement.substring(1,AddElement.length-1) + '}');
}
return object;
}
addValueInObject('sdfasfas', yourObject, 'keyname');
OR:
var obj = {'key':'value'};
obj.key2 = 'value2';
For anyone still looking for a solution, I think that the objects should have been stored in an array like...
var element = {}, cart = [];
element.id = id;
element.quantity = quantity;
cart.push(element);
Then when you want to use an element as an object you can do this...
var element = cart.find(function (el) { return el.id === "id_that_we_want";});
Put a variable at "id_that_we_want" and give it the id of the element that we want from our array. An "elemnt" object is returned. Of course we dont have to us id to find the object. We could use any other property to do the find.
My proposition is to use different data structure that proposed already in other answers - it allows you to make push on card.elements and allow to expand card properties:
let card = {
elements: [
{"id":10,"quantity":1}
],
//other card fields like 'owner' or something...
}
card.elements.push({"id":22,"quantity":3})
console.log(card);
push is an method of arrays , so for object you can get the index of last element ,and you can probably do the same job as push for object as below
var lastIndex = Object.keys(element)[Object.keys(element).length-1];
then add object to the new index of element
element[parseInt(lastIndex) +1] = { id: id, quantity: quantity };
if you not design to do loop with in JS e.g. pass to PHP to do loop for you
let decision = {}
decision[code+'#'+row] = event.target.value
this concept may help a bit
This is an old question, anyway today the best practice is by using Object.defineProperty
const object1 = {};
Object.defineProperty(object1, 'property1', {
value: 42,
writable: false
});
object1.property1 = 77;
// throws an error in strict mode
console.log(object1.property1);
// expected output: 42
In case anyone else needs this, I finally found a good way to add objects or arrays of objects:
var myobj = {}
// These two options only work for single-valued keys, not arrays or objects
myobj["a"] = 1
myobj.b = 2
// This one works for everyting:
Object.assign(myobj, {"key": "value"}); // single-value
// Add object
Object.assign(myobj, {"subobj":
{
"c": 3
}
});
// Add array of objects
Object.assign(myobj, {"subarr":
[
{
"d": 4,
},
{
"e": 5
}
]
});
var newObject = {element:{"id":10,"quantity":1}};
console.log(newObject);

Split array values to object?

I was wondering how to convert an array to an object by splitting the values ?
var obj = {
id: '',
val: ''
}
By this I mean - if I have an array like
["abc12", "abc1", "def12", "abc454"]
How I could split the first 3 values off - so it end up like an object like:
{id: 'abc', val: 12}, {id: 'abc', val: 1} ...
source.map(function(x) {
return { id: x.substr(0,3), val: +(x.substr(3)) };
}
EDIT: Not an answer to the question
This will not result in the desired mapped array, but in a single object.
Sorry, misread your question :(
The answer below will return one single Object and not an array of Objects.
You can easily fold such arrays into objects with the array's reduce method:
var source = ["abc12", "abc1", "def12", "abc454"];
var obj = source.reduce(function(o, str) {
var key = str.substr(0, 3)
var value = parseInt(str.substr(3))
o[key] = value;
return o;
}, {})
// obj = { abc: 454, def: 12 }
One solution is to map your array (like herby noted) with a function that converts an element of your array to an object of your desired form.
In this case, the id is represented by all the characters before the first digit and the val represents the digits from the back of the string :
source.map(function(x) {
return {
id: x.replace(/(^.*?)\d+$/,'$1'),
val: parseInt(x.replace(/^.*?(\d+)$/,'$1'),10)
};
});
Here's a working demo
Ps: You may want to be careful and check if the map method exists in the Array prototype chain, because older browsers may not have this implemented. Here's a link that explains how to cover this browser incompatibility : http://www.tutorialspoint.com/javascript/array_map.htm.

Categories