Compare function variable against array loop - javascript

I'm attempting to compare the value passed through the function (val) with items in an array (data.category) in order to replace my hard-coded 'cat1' and 'cat2' in the if/else statement. What I ultimately want to do is assign the appropriate $scope.catName and $scope.info for the appropriate value associated in the array.
How do I modify my code to iterate and compare?
$scope.changeRankingView = function(val){
var categoriesArray = data.category;
var categoriesArrayLength = categoriesArray.length;
for (var i = 0; i < categoriesArrayLength; i++) {
if(val === 'cat1'){
$scope.catName = data.category[0].name;
$scope.info = data.category[0].info;
}
else if(val === 'cat2'){
$scope.catName = data.category[1].name;
$scope.info = data.category[1].info;
}
}
};

I'm not completely sure I followed, but I think this would do what you are asking:
$scope.changeRankingView = function(val) {
for (var i = 0; i < data.category.length; i++) {
if(val === data.category[i]){
$scope.catName = data.category[i].name;
$scope.info = data.category[i].info;
}
}
};
I used data.category directly, because it didn't seem like categoriesArray was adding anything useful.

Related

How to Splice in a javascript array based on property?

I am getting an array of data in Angularjs Grid and I need to delete all the rows which has same CustCountry
ex - My Customer Array looks like
Customer[0]={ CustId:101 ,CustName:"John",CustCountry:"NewZealand" };
Customer[1]={ CustId:102 ,CustName:"Mike",CustCountry:"Australia" };
Customer[2]={ CustId:103 ,CustName:"Dunk",CustCountry:"NewZealand" };
Customer[3]={ CustId:104 ,CustName:"Alan",CustCountry:"NewZealand" };
So , in the Grid I need to delete all three records if CustomerCountry is NewZealand
I am using splice method and let me know how can I use by splicing through CustomerCountry
$scope.remove=function(CustCountry)
{
$scope.Customer.splice(index,1);
}
If you're okay with getting a copy back, this is a perfect use case for .filter:
Customer = [
{ CustId:101 ,CustName:"John",CustCountry:"NewZealand" },
{ CustId:102 ,CustName:"Mike",CustCountry:"Australia" },
{ CustId:103 ,CustName:"Dunk",CustCountry:"NewZealand" },
{ CustId:104 ,CustName:"Alan",CustCountry:"NewZealand" },
]
console.log(Customer.filter(cust => cust.CustCountry !== "NewZealand"));
if you have one specific country in mind then just use .filter()
$scope.Customer = $scope.Customer.filter(obj => obj.CustCountry !== "SpecificCountry")
If you want to delete all objects with duplicate countries then, referring to Remove duplicate values from JS array, this is what you can do:
var removeDuplicateCountries = function(arr){
var dupStore = {};
for (var x= 0; x < arr.length; x++){
if (arr[x].CustCountry in dupStore){
dupStore[arr[x].CustCountry] = false;
} else {
dupStore[arr[x].CustCountry] = true;
}
}
var newarr = [];
for (var x= 0; x < arr.length; x++){
if (dupStore[arr[x].CustCountry]){
newarr.push(arr[x]);
}
}
return arr;
};
$scope.Customer = removeDuplicateCountries($scope.Customer);
Or incorporating the .filter() method
var removeDuplicateCountries = function(arr){
var dupStore = {};
var newarr = arr;
for (var x= 0; x < arr.length; x++){
if (arr[x].CustCountry in dupStore){
newarr = newarr.filter(obj => obj.CustCountry !== arr[x].CustCountry);
} else {
dupStore[arr[x].CustCountry] = true;
}
}
return newarr;
};
$scope.Customer = removeDuplicateCountries($scope.Customer);
if there are many duplicate countries then use the way without .filter()

Object search works first time only

I created an object called "Jarz". Then added an object within it called 'cat'. Then I made a function to search within the Jarz object for an object called 'cat', which works. However for every object after 'cat' that I add to 'Jarz' the function will not find it in the search. Only the first run ever works. Here is the code:
var Jarz = {};
Jarz['cat'] = {};
Here is the function:
function doesObjExist(ObjName){
var tmpArr = Object.keys(Jarz);
for(var i = 0; i < tmpArr.length; i++){
if(tmpArr[i] === ObjName){
return true;
}
else {
return false;
}
}
}
When I run it on the first object 'cat' it returns true. But any obj I make after that returns false. ie:
Jarz['hat'] = {};
doesObjExist('hat') // returns false
I cant seem to find what is missing here. Any help is appreciated, thanks.
Its because when you call it with hat,it is checking first for cat as it is false your returning from the loop so it wont execute further to check for hat
change this to
var Jarz = {};
Jarz['cat'] = {};
console.log(doesObjExist('cat'));
Jarz['hat'] = {};
console.log(doesObjExist('hat'));
function doesObjExist(ObjName) {
var tmpArr = Object.keys(Jarz);
var count = 0;
for (var i = 0; i < tmpArr.length; i++) {
if (tmpArr[i] === ObjName) {
return true;
} else {
count++;
}
}
if (count >= tmpArr.length)
return false;
}
Hope this helps

making nested objects array and checking if the key exists in objs

I am trying to check if the keys exits in array of objects. I am getting false each time when I pass existing key to my function.
var connect_clients = [];
connect_clients.push({
'a': val
});
function lookup(name) {
for (var i = 0, len = connect_clients.length; i < len; i++) {
if (connect_clients[i].key === name)
return true;
}
return false;
}
console.log(lookup('a'));
Is there anything wrong?
connect_clients[i].key refers to the actual property named key, not the keys of the object.
For this case, you can use Object.keys to get an array of keys of an object and use Array.prototype.some to make sure that at least one of the objects has the key. For example,
function lookup(name) {
return connect_clients.some(function(client) {
return Object.keys(client).indexOf(name) !== -1;
});
}
Use Object.keys() to get keys of an object.
var val = 'val';
var connect_clients = [];
connect_clients.push({
'a': val
});
function lookup(keyName) {
var i;
for ( i = 0; i < connect_clients.length; i++) {
var keys = Object.keys(connect_clients[i]);
if(keys.indexOf(keyName) !== -1) {
return true;
}
}
return false;
}
console.log(lookup('a'));

how to build javascript object dynamically with array values

I need to create the object property from array values and assign some values to that for example
var main_obj = {};
var dynamic_array = ["value1", "value2", "value3", "value4"];
From dynamic_array I need to create main_obj like:
main_obj[value1][value2][value3] = some_value;
Please give me some suggestions.
dynamic_array.forEach(function(prop){
main_obj[prop] = some_value;
});
this is another way
var dynamic_array = ["value1","value2","value3"];
var value = 'your value';
function createobj(dynamic_array,value){
var count = dynamic_array.length;
var text= '';
var ended = '';
for(var i = 0; i < count; i++){
text += '{"'+dynamic_array[i]+'":';
ended +='}';
}
text += '"'+value+'"'+ended;
return JSON.parse(text);
}
console.log(createobj(dynamic_array,value));
Trying to interpretate your question, this may be a solution to what you are looking for:
function createNestedProperties(obj, array, value) {
var result = {};
var result_tmp = obj;
var i = 0;
while (i < array.length) {
if (i < (array.length - 1))
result_tmp[array[i]] = {};
else
result_tmp[array[i]] = value;
result_tmp = result_tmp[array[i]];
i++;
}
return obj;
}
used this way:
var main_obj = {"value1":{"value2":{"value3":{}}}};
var dynamic_array = ["value1", "value2", "value3"];
main_obj = createNestedProperties(main_obj, dynamic_array, {"value_Z":"new value"});
Resulting object:
{"value1":{"value2":{"value3":{"value_Z":"new value"}}}}
This function would override existing properties in main_obj if already there.
i parse through the object recursively rather than building that jQuery - How to recursively loop over an object's nested properties?
function recursiveIteration(main_obj) {
for (var property in main_obj) {
if (property == value3)
{
main_obj[property] = {"value4":test};
}
else
{
recursiveIteration(main_obj[property]);
}
}
}
recursiveIteration(main_obj);

Best way to group elements in an array with least complexity

I have a JSON array which looks like this:
var map_results = [{"Type":"Flat","Price":100.9},
{"Type":"Room","Price":23.5},
{"Type":"Flat","Price":67.5},
{"Type":"Flat","Price":100.9}
{"Type":"Plot","Price":89.8}]
This array contains about 100,000 records. I want the output to be grouped by "Type" and "Price". It should look like this:
var expected_output = [{"Type":"Flat", "Data":[{"Price":100.9, "Total":2},
{"Price":67.5, "Total":1}] },
{"Type":"Room","Data":[{"Price":23.5,"Total":1}]},
{"Type":"Plot","Data":[{"Price":89.8, "Total:1"}]}]
This has to be done in pure javascript and I cannot use libraries like undersore.js. I tried solving the problem but it had like 3 nested for loops which made the complexity as n^4. What could be a better solution for this problem??
The function I have looks like this:
var reduce = function (map_results) {
var results = [];
for (var i in map_results) {
var type_found = 0;
for(var result in results){
if (map_results[i]["Type"] == results[result]["Type"]){
type_found = 1;
var price_found = 0;
for(var data in results[result]["Data"]){
if(map_results[i]["Price"] == results[result]["Data"][data]["Price"]){
price_found = 1;
results[result]["Data"][data]["Total"] +=1;
}
}
if(price_found == 0){
results[result]["Data"].push({"Price":map_results[i]["Price"], "Total":1});
}
}
}
if(type_found == 0){
results.push({"Type":map_results[i]["Type"], "Data":[{"Price":map_results[i]["Price"],"Total":1}]});
}
}
return results;
};
I have a short function that handles the first part of the requested functionality: It maps the map_results to the desired format:
var map_results = [{"Type":"Flat","Price":100.9},
{"Type":"Room","Price":23.5},
{"Type":"Flat","Price":67.5},
{"Type":"Flat","Price":100.9},
{"Type":"Plot","Price":89.8}]
var expected_output = map_results.reduce(function(obj, current){
if(!obj[current.Type]){
obj[current.Type] = {'Type':current.Type, 'Data':[]};
}
obj[current.Type].Data.push({'Price':current.Price, 'Total':1});
return obj;
},{})
Then this piece of code is required to calculate the totals, I'm afraid:
for(var type in expected_output){
var d = {};
for(var item in expected_output[type].Data){
d[expected_output[type].Data[item].Price] = (d[expected_output[type].Data[item].Price] || 0) + 1;
}
expected_output[type].Data = [];
for(var i in d){
expected_output[type].Data.push({
'Price':i,
'Total':d[i]
})
}
}
Output:
{
"Flat":{
"Type":"Flat",
"Data":[{"Price":"100.9","Total":2},
{"Price":"67.5","Total":1}]
},
"Room":{
"Type":"Room",
"Data":[{"Price":"23.5","Total":1}]
},
"Plot":{
"Type":"Plot",
"Data":[{"Price":"89.8","Total":1}]
}
}
As the Types and the Prices are unique after grouping I think a structure like {"Flat": {"100.9":2,"67.5":1}, {"Room": {"23.5": 1}}} would be easier to handle. So could do the grouping the following way:
var output = {};
map_results.map(function(el, i) {
output[el["Type"]] = output[el["Type"]] || [];
output[el["Type"]][el["Price"] = (output[el["Type"]][el["Price"]+1) || 1;
});
If you can not handle this structure you could do another mapping to your structure.
As you are iterating the Array one time this should have a complexity of n.
Look here for a working fiddle.
EDIT: So remap everything to your structure. The order of the remapping is far less then the first mapping, because the grouping is already done.
var expected_output = [];
for(type in output) {
var prices = [];
for(price in output[type]) {
prices.push({"Price": price, "Total": output[type][price]);
}
expected_output.push({"Type": type, "Data": prices});
}
Below is yet another effort. Here's a FIDDLE
For performance testing, I also mocked up a JSPerf test with 163840 elements. On Chrome(OSX) original solution is 90% slower than this one.
Few notes:
Feel free to optimize for your case (e.g. take out the hasOwnProperty check on object cloning).
Also, if you need the latest Total as the first element use unshift instead of push to add the obj the beginning of the array.
function groupBy(arr, key, key2) {
var retArr = [];
arr.reduce(function(previousValue, currentValue, index, array){
if(currentValue.hasOwnProperty(key)) {
var kVal = currentValue[key];
if(!previousValue.hasOwnProperty(kVal)) {
previousValue[kVal] = {};
retArr.push(previousValue[kVal]);
previousValue[kVal][key] = kVal;
previousValue[kVal]["Data"] = [];
}
var prevNode = previousValue[kVal];
if(currentValue.hasOwnProperty(key2)) {
var obj = {};
for(var k in currentValue) {
if(currentValue.hasOwnProperty(k) && k!=key)
obj[k] = currentValue[k];
}
obj["Total"] = prevNode["Data"].length + 1;
prevNode["Data"].push(obj);
}
}
return previousValue;
}, {});
return retArr;
}
var map_results = [{"Type":"Flat","Price":100.9},
{"Type":"Room","Price":23.5},
{"Type":"Flat","Price":67.5},
{"Type":"Flat","Price":100.9},
{"Type":"Plot","Price":89.8}];
var expected_output = groupBy(map_results, "Type", "Price");
console.dir(expected_output);
Tried something like this:
var reduce_func = function (previous, current) {
if(previous.length == 0){
previous.push({Type: current.Type, Data:[{Price:current.Price,Total:1}]});
return previous;
}
var type_found = 0;
for (var one in previous) {
if (current.Type == previous[one].Type){
type_found = 1;
var price_found = 0;
for(var data in previous[one].Data){
if(current.Price == previous[one].Data[data].Price){
price_found = 1;
previous[one].Data[data].Total += 1;
}
}
if(price_found == 0){
previous[one].Data.push({Price:current.Price, Total:1});
}
}
}
if(type_found == 0){
previous.push({Type:current.Type, Data:[{Price : current.Price ,Total:1}]});
}
return previous;
}
map_results.reduce(reduce_func,[]);

Categories

Resources