I want to iterate through a JSON response, check to see if key,value exists and if not, add it to the array.
$scope.InitProdToArray = function (data) {
angular.forEach($scope.data.obj.Product, function(value, index) {
if (value.Product_type != 'T' ) {
$scope.data.obj.Product.push({Product_type: 'T'});
}
if (value.Product_type != '16364NB' ) {
$scope.data.obj.Product.push({Product_type: '16364NB'});
}
if (value.Product_type != '39087NB' ) {
$scope.data.obj.Product.push({Product_type: '39087NB'});
}
if (value.Product_type != 'C' ) {
$scope.data.obj.Product.push({Product_type: 'C'});
}
if (value.Product_type != '4NB' ) {
$scope.data.obj.Product.push({Product_type: '4NB'});
}
});
JSON: $scope.data.obj.Product =
[{
"Count": 28,
"Product_type": "T"
}, {
"Count": 88,
"Product_type": "4NB"
}, {
"Count": 20,
"Product_type": "C"
}, {
"Count": 3,
"Product_type": "39087NB"
}
]
This doesn't seem to work because I'm pushing the key,value pair every time it iterates through each node. I end up getting back a JSON that has multiple product_type that is the same.
Is there a way to stop the code from adding additional key,value if it already exists?
You seem to have written your type check upside down.
instead of if (value.Product_type != 'T' ) {... I would have imagine something like if (value.Product_type == 'T' ) {... this way you would push to Product array only when the type is matching.
apart from that, you can also check before pushing if you Product array already contains a key of that type : if($scope.data.obj.Product.indexOf(value.Product_type)!==undefined)
From your code it seems like you are doing search and insert rather than things to do with key/value.
If you are supporting new browsers only there is a handy function called find for this purpose.
var productTypes = ['T', '16364NB', '39087NB', 'C', '4NB'];
angular.forEach(productTypes, function(value) {
var exists = $scope.data.obj.Product.find(function(item) {
return (item.Product_type == value);
});
if (!exists) {
$scope.data.obj.Product.push({
Product_type: value,
count: 0
});
}
});
If you need to support older browsers, you'll need to add polyfill for find as well.
var TYPES = { T: 'T', NB4: '4NB', C: 'C', NB39087: '39087NB' };
var products = [{ "Count": 28, "Product_type": "T" }, { "Count": 88, "Product_type": "4NB" }];
/* check if the element key is not the specified value....*/
function isKeyInElement(keyToCheck, element) {
return element.Product_type === keyToCheck;
}
/* checks if there are NO elements in array with the specified key ...*/
function isKeyInArray(keyToCheck, array) {
return !!array.filter(function (element) { return isKeyInElement(keyToCheck, element); }).length;
}
/* another way to check if there are NO elements in array with the specified key ...*/
function isKeyInArray2(keyToCheck, array) {
return array.map(function (element) { return element.Product_type; }).indexOf(keyToCheck) > -1;
}
function initProdToArray(source) {
if (!isKeyInArray(TYPES.T, source)) { source.push({ Product_type: TYPES.T }); }
if (!isKeyInArray(TYPES.NB4, source)) { source.push({ Product_type: TYPES.NB4 }); }
if (!isKeyInArray(TYPES.C, source)) { source.push({ Product_type: TYPES.C }); }
if (!isKeyInArray(TYPES.NB39087, source)) { source.push({ Product_type: TYPES.NB39087 }); }
}
initProdToArray(products);
console.log(products);
Related
I need to remove an entry from an array by searching for the id value.
The data looks like this:
data = [ { "id": "02" }, { "id": "03" } ];
And I need a method like:
remove(keyValue) {
// do something here
}
Usage example:
remove('02');
Then it would search the id key with value "02" and remove the data so it would remove like this:
data = [ { "id": "03" } ];
How can I do this?
Works if key is "id", and if you are sure there won't be repeated values:
var data = [ { "id": "02" }, { "id": "03" } ];
function removeVal(value) {
var removeIndex = -1;
data.forEach((obj, index) => {
if (obj.id === value) {
removeIndex = index;
}
});
data.splice(removeIndex, 1);
console.log(data);
}
removeVal("02");
You could implement something like this https://stackblitz.com/edit/typescript-g3gty2
where the method remove accepts the initial array, the key and the value to remove.
function remove(data: any[], key: string, value: any) {
return data.filter(d => d[key] !== value);
}
If you use Typescript remove quotes from property names.
data = [ { id: "02" }, { id: "03" } ];
You can use findIndex function to get the index of specific element. After you got the index you can delete the element with splice function.
remove(keyValue: String) {
let objectIndex = this.data.findIndex(e => e.id == keyValue);
if(objectIndex != -1) {
this.data.splice(objectIndex, 1); // Remove one element from array
}
}
I have a below json, want to get object whose id = 111 , depth may vary depending upon the json.
object = [
{
id= 1,
name : 'a',
childNodes : [ {
id=11,
name:'aa',
childNodes:[{
id: 111,
name:'aaaa',
childNodes:[]
}]
}]
}]
required output { id: 111, name:'aaaa', childNodes:[] }
Looking for fastest algorithm or method. Data would be really huge of more then 35000 nodes and depth upto 20.
Any help would be appreciated.
Here is a recursive function using some:
function findNested(arr, id) {
var res;
return arr.some(o => res = Object(o).id === id ? o
: findNested(o.childNodes, id) ) && res;
}
var object = [{
id: 1,
name : 'a',
childNodes : [ {
id: 11,
name:'aa',
childNodes:[{
id: 111,
name:'aaaa',
childNodes:[]
}]
}]
}];
console.log(findNested(object, 111));
console.log(findNested(object, 9));
You can create recursive function for this using for...in loop.
var object = [{"id":1,"name":"a","childNodes":[{"id":11,"name":"aa","childNodes":[{"id":111,"name":"aaaa","childNodes":[]}]}]},{"id":2,"name":"a","childNodes":[{"id":22,"name":"aa","childNodes":[{"id":123,"name":"aaaa","childNodes":[]}]}]}]
function findById(data, id) {
for(var i in data) {
var result;
if(data.id == id) return data
if(typeof data[i] == 'object' && (result = findById(data[i], id))) return result
}
}
console.log(findById(object, 111))
console.log(findById(object, 22))
I have to create a javascript function to do a recursive search on an object and get the label name for the given ID.
I tried with the below code but it returns undefined for any id. Please help me to fix this issue.
function GetLabel(data, Id) {
var i,
currentChild,
result;
if (Id == data.Id) {
return data['Label'];
} else {
for (field in data) {
if (typeof(data[field]) == "object") {
result = GetLabel(data[field], Id);
if (result != "") return result;
}
if (data[field] == Id) {
result = data['Label'];
return result;
}
}
}
}
This answer is based on the data structure of this question: JSON Schema for tree structure
This proposal uses an a function for recursive call and some changes, basically for the iteration of child, which is an array instead of an object, which may supposed to be.
After a check if child is an array, Array#some helps iterating and stops if the wanted id is found.
I suggest to use a common style guide for naming convention and write all properties in small letters, as well as functions which may not be used as constructor.
function getLabel(data, id) {
var result;
if (id === data.id) {
return data.label;
}
Array.isArray(data.child) && data.child.some(function (a) {
result = getLabel(a, id);
if (result) {
return true;
}
});
return result;
}
var tree = { id: 1, label: "A", child: [{ id: 2, label: "B", child: [{ id: 5, label: "E" }, { id: 6, label: "F" }, { id: 7, label: "G" }] }, { id: 3, label: "C" }, { id: 4, label: "D", child: [{ id: 8, label: "H" }, { id: 9, label: "I" }] }] },
i;
for (i = 1; i < 10; i++) {
document.write(getLabel(tree, i) + '<br>');
}
I have an array of objects, an example of a few of them being
[
{
"lang_code": "eng",
"site_language": "1",
"name": "English"
},
{
"lang_code": "afr",
"site_language": "1",
"name": "Afrikaans"
},
{
"lang_code": "ale",
"site_language": "0",
"name": "Aleut"
},
]
I want to be able to search the whole array for a specific lang_code, let's say I use eng. I want to search the whole array for eng. If it's there, I want it to return English, if not, I want it to return invalid. Any ideas on this?
A generic and more flexible version of the findById function above:
// array = [{key:value},{key:value}]
function objectFindByKey(array, key, value) {
for (var i = 0; i < array.length; i++) {
if (array[i][key] === value) {
return array[i];
}
}
return null;
}
var array = your array;
var result_obj = objectFindByKey(array, 'lang_code', 'eng');
Click here for demo
You could use filter:
function findLang(arr, code) {
var filtered = arr.filter(function (el) {
return el.lang_code === code;
});
// filter returns an array of objects that match the criteria
// if the array is not empty return the language,
// otherwise return 'invalid'
return filtered.length > 0 ? filtered[0].name : 'invalid';
}
findLang(arr, 'eng'); // English
DEMO
If you wanted to add map into the mix instead of using that ternary operation (but which would most likely be slower and doesn't really provide any additional benefit):
function findLang(arr, code) {
return arr.filter(function (el) {
return el.lang_code === code;
}).map(function (el) {
return el.name;
})[0] || 'invalid';
}
DEMO
How about a for loop. Something like:
function find_lang(input_arr, lang_code) {
for(var i = 0; i < input_arr.length; i++) {
var o = input_arr[i];
if( o.lang_code === lang_code ) {
return o.name;
}
}
return "invalid";
}
Underscore.js has some useful helpers for this kind of thing: http://underscorejs.org/
E.g Find:
Looks through each value in the list, returning the first one that
passes a truth test (predicate), or undefined if no value passes the
test. The function returns as soon as it finds an acceptable element,
and doesn't traverse the entire list.
var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> 2
Where:
Looks through each value in the list, returning an array of all the
values that contain all of the key-value pairs listed in properties.
_.where(listOfPlays, {author: "Shakespeare", year: 1611});
=> [{title: "Cymbeline", author: "Shakespeare", year: 1611},
{title: "The Tempest", author: "Shakespeare", year: 1611}]
You could do it this way:
// configure your parameters
function checkArr(){
for (var i = 0; i < x.length; i++){
if (x[i].lang_code == "eng")
return "English";
}
return "invalid";
}
var x = [
{
"lang_code": "eng",
"site_language": "1",
"name": "English"
},
{
"lang_code": "afr",
"site_language": "1",
"name": "Afrikaans"
},
{
"lang_code": "ale",
"site_language": "0",
"name": "Aleut"
}
];
I get an array of objects from a MongoDB through API.
I then need to filter the result furthermore (client side).
I'll work with long lists (could be some thousand of results), each object has about 10 properties with some arrays in it.
Example of an object:
{
_id: xxxxxxx,
foo: [
{ a: "b", c: "d" },
{ a: "b", c: "d" }
],
data: {
a: "b",
c: "d"
}
}
I loop the array async to improve speed:
async.filter(documents, function(value) {
// Search inside the object to check if it contains the given "value"
}, function(results) {
// Will do something with the result array
});
How can I search inside the current object to check if it contains the given value without know in which property I'll find the value?
Though I've not included the async part but I believe overall searching approach could be like this:
// Input Array
var inpArr = [{
id: 1,
foo: [{
a: "dog",
b: "cat"
}]
}, {
id: 2,
foo: [{
a: "kutta",
b: "billi"
}]
}];
var myFilter = function(val, item, index, array) {
var searchResult = scanProperties(item, val);
return searchResult;
};
// Note: pass additional argument to default filter.
// using Function.Prototype.Bind
var filterResult = inpArr.filter(myFilter.bind(null, "dog"));
alert(filterResult);
console.log(filterResult);
// Recursively scan all properties
function scanProperties(obj, val) {
var result = false;
for (var property in obj) {
if (obj.hasOwnProperty(property) && obj[property] != null) {
if (obj[property].constructor == Object) {
result = result || scanProperties(obj[property], val);
} else if (obj[property].constructor == Array) {
for (var i = 0; i < obj[property].length; i++) {
result = result || scanProperties(obj[property][i], val);
}
} else {
result = result || (obj[property] == val);
}
}
}
return result;
};
JS Fiddle Searching an Array of Objects
You can simply iterate through each and every item recursively, like this
var data = {
_id: 1243,
foo: [{
a: "b",
c: "d"
}, {
a: "b",
c: "d"
}],
data: {
a: "b",
c: "d"
}
};
function findValue(value) {
function findItems(document) {
var type = Object.prototype.toString.call(document);
if (type.indexOf("Array") + 1) {
return document.some(findItems);
} else if (type.indexOf("Object") + 1) {
return Object.keys(document).some(function(key) {
return findItems(document[key]);
});
} else {
return document === value;
}
}
return findItems;
}
console.log(findValue('dd')(data));
# false
console.log(findValue('d')(data));
# true