Find in JSON array by manually entered ID - javascript

in my angularjs app I get JSON object from API.
I have an input field, where I can input ID manually, and if an item with this ID exists, I need to change his property.
I also store this ID to sessionStorage, so when user refresh page, he get value like before refresh.
Here is json from API where I need to change ON THE FLY property SHOW to true if exist
$scope.tableParams.data = [
{id: 1015, type: "ssss", show: false},
{id: 1016, type: "ssss", show: false},
{id: 1017, type: "ssss", show: false},
{id: 1018, type: "ssss", show: false}
]
Function for getting input value and store to session storage, and also change SHOW property
$scope.getIndex = function (indexOfRow) { //indexOfRow is passed data from input field
//here I want to change show to true for passed id
sessionStorage.setItem("indexOfOpenedRow", JSON.stringify(indexOfRow));
}
I try answer from here but not working for me
I also try this, but allways get undefined
function findId(array, id) {
var i, found, obj;
for (i = 0; i < array.length; ++i) {
obj = array[i];
if (obj.id == id) {
console.log(obj);
return obj;
}
}
return undefined; // <= You might consider null or undefined here
}
$scope.getIndex = function (indexOfRow) { //indexOfRow is passed data from input field
//here I want to change show to true for passed id
angular.forEach($scope.tableParams.data, function(key, value){
var result = findId(key.id, indexOfRow);
console.log(result);
});
sessionStorage.setItem("indexOfOpenedRow", JSON.stringify(indexOfRow));
}

Filter is the function you are searching for. As i understood your question by reading your code you want to compare an seperate ID with the ID in the JSON? If I am wrong commend here and I will edit the answer:
function findIDAndSetShowingTrue(array, id) {
return array.filter(curr=> curr.id === id).map(curr => ({...curr, show: true}));
}
The filter function iterates over every child inside the array and gives you the specific value (array.filter).
Then you can use this child and compare it like an if statement with some other values (current).
In the end you compare current.id and your input id (current.id === id) and return the current object if it's true.

Related

Getting sum() of an attribute in loopback without looping through all instances of the object

I have a model DummyModel that has the attributes attOne, attTwo and attThree.
To get all the instances of attOne, one can use-
DummyModel.find({where: {attTwo: 'someValue'}, fields: {attOne: true} });
The above query corresponds more or less to the MySQL query -
select attOne from DummyModel where attTwo = 'someValue'
However, I need to find the sum of all the attOne values returned from the above query. That is, the MySQL equivalent of -
select sum(attOne) from DummyModel where attTwo = 'someValue'
I read that loopback doesn't support aggregrate functions (i.e. groupby). But is there any way to getsum(attOne)?
I know one way is to get the object and then loop over all the instances and add it.
What I want to know is if there's any pre-existing loopback method to do the same.
Supposing that this code
f = DummyModel.find({where: {attTwo: 'someValue'}, fields: {attOne: true} });
returns an array like this
[
{attTwo: 'someValue' ,attOne: 1}
{attTwo: 'otherValue',attOne: 1}
]
you can use the reduce function to apply a function to all elements
var sum = f.reduce(function(last, d) {return d.attOne + last},0);
And here is the working code
DummyModel = {
find: function(a) {
return [{
attTwo: 'someValue',
attOne: 1
}, {
attTwo: 'otherValue',
attOne: 2
}];
}
}
f = DummyModel.find({
where: {
attTwo: 'someValue'
},
fields: {
attOne: true
}
});
sum = f.reduce(function(last, d) {
return d.attOne + last;
}, 0);
alert(sum);

Updating an object in array

I am trying to update a object in an array that is two-way binded to a directive but its not working at all.
I am doing the following to update it:
$filter('filter')
($scope.offers, {id: offer_id})[0].status = "active";
I get no console errors but if I console.log $scope.offers after the filter code is executed, the status is not updated.
What I am trying to accomplish is to update an object in $scope.offers array with a new value. Every object in the array has a id attribute that is unique which I am trying to select it by.
Hope this information is sufficient. Thanks!
Here you are updating the status of outcome of the filter expression.
That means $filter('filter')($scope.offers, {id: offer_id}) itself returns an array. And you are updating that array, not the actual array.
I believe, $scope.offers is two way binded and you are not updating it.
I hope this makes some sense. And if you can explain what exactly you want. Then I can put some more light.
EDIT
So, i think once you get the new status value and the id on which you need to update. You can simply iterate the array using simple for loop and check for id and if it matches update the status. Something like this.
for(var i=0; i<array.length; i++) {
if (array[i].id === requiredId) {
array[i].status = newStatus;
break;
}
}
Hope, this helps.
Using native JS methods the updateArrObj function below utilizes some to search for an object that matches the specified id and then using a more generic update approach will map an update object onto the original object. The main benefit of using some is twofold: you get a boolean value to indicate if an update occurred and also it will stop searching the array after it makes an update.
function updateArrObj(arr, id, update) {
return arr.some(function findObj(obj) {
if (obj.id === id) {
Object.keys(update).forEach(function updateObj(key) {
obj[key] = update[key];
});
return true;
}
});
}
var arrObj = [
{id: 1, status: 'inactive'},
{id: 2, status: 'inactive'},
{id: 3, status: 'inactive'},
{id: 4, status: 'inactive'},
{id: 5, status: 'inactive'}
];
var updated = updateArrObj(arrObj, 3, {status: 'active'});
document.write(
'<h3>Updated: ' + updated + '</h3>' +
'<pre>' + JSON.stringify(arrObj, null, 4) + '</pre>'
);
function updateArrObj(arr, id, update) {
return arr.some(function findObj(obj) {
if (obj.id === id) {
Object.keys(update).forEach(function updateObj(key) {
obj[key] = update[key];
});
return true;
}
});
}

Get the lower integer id not already used in Javascript

I have a list of JS objects defined by an integer ID.
objects = [{
id: 0,
type: 'null'
}, {
id: 1,
type: 'foo'
}, {
id: 2,
type: 'bar'
}];
I implemented a function to remove an element from my list :
removeObject = function(o){
objects.splice(objects.indexOf(o), 1);
}
My problem is that I need to create a function to add a new item in my list with a id not already used (for example the lower positive integer not present in the list).
I tried to do something like that but it did not work when I remove the object 0 (for example).
addObject = function(type){
objects.push({
id: objects.length,
type: type
});
};
How can I do this ?
EDIT 1
According to your answers, I assume that the best solution in term of performance is to just use a topId which is always incremented when I add a new object in my list.
But that do not answer to my requierement. Actually I think that #X-Pippes response could be good.
Should I do someting like that :
objects = [{
id: 0,
type: 'null'
}, {
id: 1,
type: 'foo'
}, {
id: 2,
type: 'bar'
}];
// Init available ids list with the default value
availableIds = [objects.length];
removeObject = function(o){
// Remove the object from the list
objects.splice(objects.indexOf(o), 1);
// Add its id to the available ids list
availableIds.push(o.id);
}
addObject = function(type){
// Get lower id available
var newId = Math.min.apply(Math,availableIds);
// Push the new object with the id retrieved
objects.push({
id: newId,
type: type
});
// Remove used id from the available ids list
availableIds.splice(availableIds.indexOf(newId), 1);
// Add a default id if available list is empty
if(availableIds.length < 1) availableIds.push(objects.length);
};
if you remove for instance 0 and the next addObject is 0 you have to do something like:
keep a list [initial empty] with every ID removed. When you need to add a new one, pick the shorter, add and delete from list.
Also keep a var with the biggest ID added. If the previous list is empty, add +1 to the var and addObject with that id
Use the correct structures. A JavaScript object will do the job. It guarantees that you only get one item for key, you can look up and remove by key in probably O(1)ish. No point trying to re-implement it in a less efficient manner, which will be O(n) lookup.
var structure = {
objects : {},
topId : 0
}
structure.add = function(item) {
var id = this.topId ++;
structure.objects[id] = item;
}
structure.add("thing")
structure.add("other thing")
structure.add("another thing")
structure.objects
>>> Object {0: "thing", 1: "other thing", 2: "another thing"}
structure.objects[1]
>> "other thing"
Then the normal index operations to get/set/delete.
If you use that function then you have an invariant (guarantee) on your data structure that you won't use the same ID twice.
You need a function to find the first free number:
addObject = function(type){
objects.push({
id: firstOpenIndex(),
type: type
});
};
firstOpenIndex = function() {
for(var idx = 0; true; i++) {
var found = false;
for(var o in objects) {
if (objects[o].id == idx) {
found = true;
break;
}
}
if (!found) return idx;
}
}
In Javascript MaxInt is 9007199254740992. Why not just keep incrementing?
You can and probably should just use an array(s) like:
objects.type=['null','foo','bar'];
to add an object see:
How to append something to an array?
to find a value: var index = objects.type.indexOf('foo');
to find 1st empty field var index = objects.type.indexOf(''); which you can use to find the element for adding (if index is -1 use objects.type.length) if you "delete" an element by setting it to "" or... unless you have specific reason for keeping the "ID" static (in this case the array index), remove the element and only append new ones to the end
to remove an element see:
How do I remove a particular element from an array in JavaScript?
which will allow you to just push/append the next data.
if you need a new object array with empty fields to fill because you get new data to track:
object.newField=new Array(objects.type.length);
If you get to this point where your object contains multiple arrays, you will probably want to create functions for insert/add and delete/remove, so you don't do an operation on 1 and not the other.
Everything is already built in (read likely already pretty fast) and you don't need to reinvent constructors for your really cool object type.

Delete an element inside a JSON array by value with jQuery

Part of my json Array
var videos = $j.parseJSON('
[
{ "privacy":"public",
"id":"1169341693" },
{ "privacy":"private",
"id":"803641223" },
{ "privacy":"public",
"id":"1300612600" }, ......
When I console.log the element I'm getting
[Object, Object, Object, …]
0: Object
privacy: "public"
id: "1169341693"
1: Object
privacy: "private"
id: "803641223"
2: Object
privacy: "public"
id: "1300612600"
I also have a unique id I want to search for
var uniqueId = 803641223;
I want to find, in my videos array, the right id, and delete that whole array element. So In that case, I want my final videos array to contain only 2 object, instead of 3 :
var videos = $j.parseJSON('
[
{ "privacy":"public",
"id":"1169341693" },
{ "privacy":"public",
"id":"1300612600" }, ......
My problem is how to get in the array to do my splice. I prefer to do it with jQuery
Any help please?
You can use grep :
videos = $.grep(videos, function(e) { return e.id!='803641223' });
In vanilla JavaScript you could have used the similar filter function but it's not supported by IE8.
Please note that videos is a JavaScript array, it's not a JSON array, even if it was made by parsing a JSON string.
A non-jQuery solution that modifies the array in place:
var uniqueId = 803641223;
var videos = [
{ "privacy":"public",
"id":"1169341693" },
{ "privacy":"private",
"id":"803641223" },
{ "privacy":"public",
"id":"1300612600" }
];
function cleaner(arr, id) {
for (var i = 0; i < videos.length; i++) {
var cur = videos[i];
if (cur.id == uniqueId) {
arr.splice(i, 1);
break;
}
}
}
cleaner(videos, uniqueId);
http://jsfiddle.net/4JAww/1/
Note that this modifies the original array in place, such that the original videos array will have the items you want, and the one that matched the uniqueId will be gone (forever). So it depends on whether you want to be able to access the original array ever again, or are okay with modifying it.
It just loops through the elements of the array, compares the item's id property to the uniqueId value, and splices if they match. I use break; immediately after the splice because you seem to imply that the uniqueId can/should only appear once in the array since it's...unique.
Hello you can remove element with javascript splice function...
videos.items.splice(1, 3); // Removes three items starting with the 2nd,
It worker for me.
arrList = $.grep(arrList, function (e) {
if(e.add_task == addTask && e.worker_id == worker_id) {
return false;
} else {
return true;
}
});
It returns an array without that object.
Hope it helps.

easiest way to search a javascript object list with jQuery?

What is the easiest way to search a javascript object list with jQuery?
For example, I have the following js config block defined:
var ProgramExclusiveSections =
{
"Rows":
[
{ 'ProgramId': '3', 'RowId': 'trSpecialHeader'},
{ 'ProgramId': '3', 'RowId': 'trSpecialRow1' },
{ 'ProgramId': '3', 'RowId': 'trSpecialRow2' },
{ 'ProgramId': '1', 'RowId': 'trOtherInfo' }
]
}
The user has selected Program ID = 3 so I want to get only the "rows" that I have configured in this js config object for Program ID = 3. This will get me the javascript object list:
var rows = ProgramExclusiveSections.Rows
but then I need to filter this down to only where RowId = 3. What's the easiest way for me to do this with jquery?
$.grep()
var matches = $.grep(rows, function (elt)
{
return elt.ProgramId === '3';
});
$.map() would do it (although $.grep() is more elegant).
var objs= $.map(ProgramExclusiveSections.Rows, function(obj, index) {
return obj.RowId === "3"? obj : null;
});
This will return an array of the objects with RowId "3" (notice you have a string and not a number).

Categories