I'm trying to check if an object in an array has a key before performing a map.
My initial object array looks like:
[{label: "", value: ""}, {label: "", value: ""}]
I have a method which changes the above array so that I can post it back. This then looks like:
["STRING","STRING"]
The method I'm trying is:
var returiningUsers = [];
if (this.state.users.length > 0) {
returiningUsers = this.state.users.map(user => user.value)
console.log('has users with value');
}
return returiningUsers
The above works if there are 2 or more items in the array. When the array structure changes I get the following error: TypeError: _this.state.users.map is not a function.
I need to check if the object array key exists before doing the map function. Is this possible?
Javascript has an object property for this
myObj.hasOwnProperty('key')
I'm not sure what you mean by "changes the structure" but you can also just filter the array for objects that have the key you are looking for
if (this.state.users.length > 0) {
returiningUsers = this.state.users.filter(user => user.hasOwnProperty('value'))
}
Related
I have an associate array with the key is the Id of the item. For example, the item id is 104, therefore the id of the object will be array[104] = {item.info};
So I have this in my component, but every time I am outputting my array it shows 1-103 values and all of them are null. How would I get rid of it and make the array output only what is stored.
JavaScript does not have associative array like in PHP.
What JavaScript has that is most similar to associative array is an object. The difference is that an object is not iterable, while an associative array is iterable.
What you currently do is basically:
const data = []; // [] is an array
data[10] = {
item: 1
};
console.log(data);
What you need to do should be something like this:
const data = {}; // {} is an object
data[10] = {
item: 1
};
console.log(data);
When you do json_encode() in PHP, it is actually converting associative array into a JSON, which is a valid JavaScript object, which do not support associative array as well.
So what it does would be something like this:
$data = [
'10' => [
'item' => 1
]
];
echo json_encode($data);
// output => { "10": { "item": 1 } }
Notice the {} syntax instead of [] syntax.
array doesn't have key, value. it just have value
if you use key, value data form, you should use object
let item = {104: item.info}
how to use object :
item[104]
I am currently making a call to a service which sends a response as an array of objects with name value pairs. An example of this can be seen below. There could be any amount of these name value pairs in any order but I just want to access the value for the name "name2". Is there an efficient way other than looping through each object and checking the name to obtain the corresponding value for name2?
[{"name":"name1","value":"value1"},{"name":"name2","value":"value2"}]
So from the above data set I would want an efficient way to search for name2 and get the corresponding value "value2".
Thanks
Unless you know the specific index of the object with the name name2 no.
You'll need to iterate until you find that name then you can bail out.
e.g.
var jsonData = [{"name":"name1","value":"value1"},{"name":"name2","value":"value2"}];
for(var i=0;i<jsonData.length;i++){
if(jsonData[i]['name'] == 'name2'){
console.log('The value is: ' + jsonData[i]['value']);
break;
}
}
Note that if you don't need to support Internet Explorer, you can use the Array.find() method to simplify this.
if you don't want to iterate over the array manually you can use lambda expression as the following
a =[{"name":"name1","value":"value1"},{"name":"name2","value":"value2"}] ;
//get the items that match your criteria
a.filter(item=>item.name=="name2")
//get those items' values
a.filter(item=>item.name=="name2").map(item=>item.value)
//get the first value (if you know that it's only one item that will match)
a.filter(item=>item.name=="name2").map(item=>item.value)[0]
You can use Array#find method.
var arr = [{
"name": "name1",
"value": "value1"
}, {
"name": "name2",
"value": "value2"
}];
// get the object containing name as `name2`
var obj = arr.find(function(v) {
return v.name === 'name2';
});
// get value property if object is defined
var res = obj && obj.value;
console.log(res)
I have a $http service that retrieves user payment data. This data comes in the form of a JSON object - I asked for an array but the backend guys gave me an object! The object data structure looks something like this...
{
creditCardData: Array[3], // this is an array of objects, each object is Credit Card data, in this case the array has 3 objects but can have many
directDebitData: Array[0] // this is an array of objects, each object is Direct Debit data, the arrray is empty here, but the array can have unlimited objects
errorMessage: null // this is either null or a string
invoiceData: Array[1] // this is an array of objects, each object is Invoice data, in this case the array has 1 objects...
paymentAvailable: true // a boolean
selectedCreditCardData: Object // this is either an object or null
selectedDirectDebitData: null // this is either an object or null
selectedInvoiceData: null // this is either an object or null
}
Now I have an ng-repeat in my view and I wish to only repeat on certain items, so I wish to be able to check by key value (name) and only show the data if there is a match, so for example only show data for the keys with names 'creditCardData', 'directDebitData', 'invoiceData'.
My plan was to have a custom filter that would determine the key name/value and then add this to a new object if applicable before returning the object, something like this:
<!-- paymentData = $scope.paymentData - an object like the one above -->
<div data-ng-repeat="(key, prop) in paymentData track by $index | ObjectKeyFilter:prop:key">
And My filter (not tested) would be like so...
.filter('ObjectKeyFilter', function () {
return function (item, prop, key) {
// items is the ng-repeat index, prop the data and key the name
var tempObj = {}
// do comparison on key create a new object... ImportantL this logic may not be correct at this stage, for explaination only
if(key === 'directDebitData' || key === 'creditCardData' || key === 'invoiceData') {
tempObj[key] = prop;
}
return tempObj;
};
});
Now so far I get the following error and I don't know why as I am using the track by syntax - Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: (key, prop) in paymentData track by $index | ObjectKeyFilter:prop:key, Duplicate key: undefined, Duplicate value: []
I am unsure if my approach is correct and whether a custom filter is approproate. A colleague has told me (and I have checked this in the documentation) that filters should only be used when iterating through Arrays and not with objects! My question is... is using a custom filter correct with my current situation / requirements?
Thanks in advance. If my wording is bad just add a comment and I will edit to be more clear.
app.filter('ObjectKeyFilter', function () {
return function (item) {
var tempObj = {}
angular.forEach(item, function(value, key) {
if(key === 'directDebitData' || key === 'creditCardData' || key === 'invoiceData') {
tempObj[key] = value;
}
});
return tempObj;
};
});
In html:
<div data-ng-repeat="(key, prop) in (data | ObjectKeyFilter) track by $index">
http://plnkr.co/edit/jITyqNmkJMiSc7NmeA19?p=preview
P.S. If you are not satisfied with data retrieved from rest call, you can just change it manually - reorder whatever, etc. I.e. in ng-resource there is transformRequest function for this.
I have two arrays of data:
markerArray = [{
properties: {id: 1}
},
{
properties: {id: 2}
}];
and
data = [
{ id: 1},
{ id: 2},
{ id: 3}
]
I want to, as quickly as possible, create a new array of objects from data that have an id that does not exist in markerArray's properties.id
Lodash / underscore are an option.
Not sure about the fastest, but certainly the simplest is with lodash:
_.difference(_.pluck(data, "id"),
_.pluck(_.pluck(markerArray, "properties"),"id"));
Suggest you map an array that just contains the ID's first:
var idArray= markerArray.map(function(item){
return item.properties.id
});
//[1,2]
Then to find matches that don't exist in id array:
var result = data.filter(function(item){
return idArray.indexOf(item.id) === -1;
});
You could use map to map the IDs and then use filter to look into your data array:
var ids = markerArray.map(function(item) {
return item.properties.id;
});
var result = data.filter(function(item) {
return ids.indexOf(item.id) < 0;
});
Here's a lodash solution:
_.reject(data, _.flow(
_.identity,
_.property('id'),
_.partial(_.includes, _.map(markerArray, 'properties.id'))
));
Basically, you want to use reject() to remove the unwanted items from data (by creating a copy, not by modifying the original). We use flow() to build the callback function that decide which items are rejected. Here's the breakdown:
Callback functions passed to reject() are given several arguments - we only care about the first one. This is what identity() does, it passes the first argument to the next function in flow().
The property() function returns a new function. This new function will return the id property of the given item. Again, this id is input for the next flow() function.
We then use partial() to do the actual filtering. The partially-applied argument is an array of IDs from the markerArray. The function we're creating a partial from is includes(). If the id from data is in this array, we can remove it from the results.
I've got an 'filter' object like
{
name: 'text',
value: 'xxx',
field: 'firstname'
}
which represents a filter for a field and is updated when I change values of input fields.
I try to store this in an array in the following way:
$scope.active_filters[filter.field] = filter;
So that I know on which field I got which filter.
The filtering should happen on server side and so I'm trying to send this array to my API.
$http.post(url, $scope.active_filters)
As I can see in Chrome I've got an array with the desired element in it but length 0
[status: Object]
length: 0
status: Object
field: "status"
name: "text"
value: "x"
__proto__: Object
__proto__: Array[0]
But the object is NOT sent in my request. If I add the object via $scope.active_filters.push(filter) it IS sent to the server but it has the index 0 and not my desired value.
How can I achieve both of my targets? A named index in my array and sending the data to the api.
I'm guessing here but your code is like this:
var assoc_array = [];
assoc_array["foo"] = "bar";
assoc_array["ipsum"] = "lorem";
JavaScript doesn't know associative arrays like for instance PHP does. JavaScript has objects, and since everything is an object (even arrays) you can get this situation.
Rather than setting the elements in the array you're assigning properties to the object. This means the magical .length property doesn't get updated because the array is still empty.
If you change you code to:
var assoc_array = {}; // <-- {} instead of []
assoc_array["foo"] = "bar";
assoc_array["ipsum"] = "lorem";
You will get an Object (instead of an Array) and you wont have a .length property.
This is how you would use an Array
var indexed_array = [];
indexed_array[0] = "bar";
indexed_array[1] = "lorem";
indexed_array.length; // 2
indexed_array[100] = "foo";
indexed_array.length; // 101 - arrays are never sparse in JS, PHP will give 3
indexed_array[2]; // undefined