Querying Array of objects using javascript - Helper functions - javascript

if you are looking for Get/Delete/Sum/IsExist functions for an array of objects using javascript, I have posted this question and answer for such functions
Remove Object from an Array using JavaScript
Is Exist for an Object from an Array using JavaScript
Select Object from an Array using JavaScript
Sum Object values in an Array using JavaScript

How do I check if an array includes an object in JavaScript?
How do I remove a particular element from an array in JavaScript?
Find object by id in an array of JavaScript objects
summing numbers stored in an array in JavaScript, sum values of a javascript array?, Loop through array and return sum of all values
Btw, your question doesn't have much to do with JSON, and naught with jQuery.

Just use underscore.
Remove from a simple array:
var newList = _.without(list, 'hello', 'world'); // Remove any instance of 'hello' and 'world'
Remove from an array of objects:
var toRemove = _.where(list, {title: 'hello', subtitle: 'world'});
var newList = _.difference(list, toRemove);
Exists in array:
var exists = _.contains(list, value);
Get item from array:
var item = _.find(list, function(i){ i === value }); // For simple types
var item = _.findWhere(list, {title: 'hello', subtitle: 'world'}); // For complex types
Sum items:
var sum = _.reduce(list, function(start, num){ return start + num; }, 0);
And A LOT more.

4 Javascript Helpers
Remove Object from an Array using JavaScript
Is Exist for an Object from an Array using JavaScript
Select Object from an Array using JavaScript
Sum Object values in an Array using JavaScript
var JShelpers = {
removeItemFromArray: function (myObjects, prop, valu) {
return myObjects.filter(function (item) {
return item[prop] !== valu;
});
},
isExistInArray: function (myObjects, prop, valu) {
var i = myObjects.length;
while (i--) {
if (myObjects[i][prop] == valu) {
return true;
}
}
return false;
},
getItemFromArray: function (myObjects, prop, valu) {
var i = myObjects.length;
while (i--) {
if (myObjects[i][prop] == valu) {
return myObjects[i];
}
}
return "";
},
sumItemInArray: function (myObjects, prop) {
var summation = 0;
myObjects.forEach(function (item) {
summation += parseFloat(item[prop]);
});
return summation;
}
}
Example:
Say you have an array of Employees in a Json Format like this
var employeesArray = [{"Id":1,"Name":"tom","Age":15},{"Id":2,"Name":"Harry","Age":17}];
And you want to retrieve employee by his Age not only ID (as common) ,
you can simply call
JShelpers.getItemFromArray(employeesArray,"Age",15)

Related

Return the key from a JavaScript array?

Using PHP I can return the key by looking up the value inside an array.
<?php
$array = array(
'fruit1' => 'apple',
'fruit2' => 'orange',
'fruit3' => 'grape',
'fruit4' => 'apple',
'fruit5' => 'apple');
while ($fruit_name = current($array)) {
if ($fruit_name == 'apple') {
echo key($array).'<br />';
}
next($array);
}
?>
But I'm learning javascript, I've searched and haven't found a solution, I'm still a beginner.
How can I return the key by fetching the value within a given array?
I've already tried using its functions: .indexOf() or .findIndex()
var array = [];
array['key'] = 'Value';
array['car'] = 'Ferrari';
array['car2'] = 'BMW';
console.log(key='Ferrari'??);
How to Return 'car' if Value = 'Ferrari' ?
another doubt in this case is it better to use Array or Class? Is it possible to return the class key?
var pessoas = {'car': 'Ferrari', 'car2':'BMW'};
Arrays don't have keys, only numeric indexes. When you pass a string to an Array, you are actually creating a new property for the Array object, not a new item in the Array data (for example, .length is a property of an Array, not an indexed value).
var array = [];
// The following 3 lines don't create indexed values in the array:
array['key'] = 'Value';
array['car'] = 'Ferrari';
array['car2'] = 'BMW';
// Which is proven here:
console.log(array.length); // 0
// What they do is create new properties on the Array instance:
console.log(array.car2); // "BMW"
If you need keys, use an object, which is structured as follows:
{key: keyValue, key: keyValue, key:keyValue ...}
where the key is always a string, so quotes around the key name are not necessary.
var pessoas = {car: 'Ferrari', car2:'BMW'};
console.log("The second car is: " + pessoas.car2);
console.log("The keys and key names are: ");
for (var prop in pessoas){
console.log(prop + " : " + pessoas[prop]);
}
You should use Objects instead of arrays in JavaScript to store PHP equivalent of arrays with keys. In JS if you make an array, add non numeric keys to it and then do .length it will give 0. So many built in functions do not work, like .filter .find and .map.
//your way
let pessoas = [];
pessoas ["car1"] = "Ferrari";
pessoas ["car2"] = "BMW";
//the safe way. Both ways work.
pessoas = {'car': 'Ferrari', 'car2':'BMW'};
function getObjKey(obj, value) {
return Object.keys(obj).find(key => obj[key] === value);
}
console.log(getObjKey(pessoas, 'BMW'));
Additionally, you can turn string-keyed arrays into object like this:
function getObjKey(obj, value) {
return Object.keys(obj).find(key=>obj[key] === value);
}
var arrayToObject = (array)=>Object.keys(array).reduce((acc,curr)=>(acc[curr] = array[curr],
acc), {});
let pessoas = [];
pessoas["car1"] = "Ferrari";
pessoas["car2"] = "BMW";
pessoas.push("corretArray");
pessoas = arrayToObject(pessoas);
console.log(getObjKey(pessoas, 'BMW'));

How can I loop over an array of objects without Object.keys()?

I'm a beginner at JavaScript and I'm trying to solve this problem without Object.keys() or any regex. I have a working solution but I'm wondering if there's a better way to call on the object key within the array while still looping. If anyone has a way to do this that's basic please let me know.
Problem:
Create a function called keyCount which accepts two parameters, an array of objects, and a string. The function should return a number which is the number of times that key appears in the array of objects.
Expected Result:
countTimesOfKey([{name:"Sharon"}, {name: "Manish"},{lastName: "Terma"}], "name")) // 2
My Answer:
function countTimesOfKey(arr, str) {
let count = 0
for (let i in arr){
let test = arr[i]
let test2 = test[str]
if (test2 !== undefined){
count += 1
}
}
return count
}
You can use Array.filter to filter out the items in the array which have str as a property (by using Object.hasOwnProperty), then return the length of the resulting array:
function countTimesOfKey(arr, str) {
return arr.filter(e => e.hasOwnProperty(str)).length;
}
console.log(countTimesOfKey([{
name: "Sharon"
}, {
name: "Manish"
}, {
lastName: "Terma"
}], "name"))
Of course, using Object.keys() and #Spectric's solution are way better than the one below, I just wanted to show that we can even more 'simplify' this.
We can use for...in to
Loop over each object in the array
Loop over each key of the object on the current index
Compare the name of each key against our check variable
Increase our counter
return the result counter
const result = countTimesOfKey([{name:"Sharon"}, {name: "Manish"},{lastName: "Terma"}], "name");
console.log(result);
function countTimesOfKey(arr, name) {
let counter = 0;
for (a in arr) {
for (let k in arr[a]) {
if (k === name) {
counter++;
}
}
}
return counter;
}

Reduce JSON with JS

I am trying to reduce a JSON array. Inside the array are other object, I am trying to turn the attributes into their own array.
Reduce Function:
// parsed.freight.items is path
var resultsReduce = parsed.freight.items.reduce(function(prevVal, currVal){
return prevVal += currVal.item
},[])
console.log(resultsReduce);
// two items from the array
// 7205 00000
console.log(Array.isArray(resultsReduce));
// false
The reduce function is kind of working. It gets both item from the items array. However I am having a couple problems.
1) The reduce is not passing back an array. See isArray test
2) I am trying to make a function so I can loop through all of the attributes in the array the qty, units, weight, paint_eligable. I cannot pass a variable to the currVal.variable here
Attempting:
var itemAttribute = 'item';
var resultsReduce = parsed.freight.items.reduce(function(prevVal, currVal){
// pass param here so I can loop through
// what I actually want to do it create a function and
// loop through array of attributes
return prevVal += currVal.itemAttribute
},[])
JSON:
var request = {
"operation":"rate_request",
"assembled":true,
"terms":true,
"subtotal":15000.00,
"shipping_total":300.00,
"taxtotal":20.00,
"allocated_credit":20,
"accessorials":
{
"lift_gate_required":true,
"residential_delivery":true,
"custbodylimited_access":false
},
"freight":
{
"items":
// array to reduce
[{
"item":"7205",
"qty":10,
"units":10,
"weight":"19.0000",
"paint_eligible":false
},
{ "item":"1111",
"qty":10,
"units":10,
"weight":"19.0000",
"paint_eligible":false
}],
"total_items_count":10,
"total_weight":190.0},
"from_data":
{
"city":"Raleigh",
"country":"US",
"zip":"27604"},
"to_data":
{
"city":"Chicago",
"country":"US",
"zip":"60605"
}
}
Thanks in advance
You may need Array#map for getting an array of items
var resultsReduce = parsed.freight.items.reduce(function (array, object) {
return array.concat(object.item);
}, []);
The same with a given key, with bracket notation as property accessor
object.property
object["property"]
var key = 'item',
resultsReduce = parsed.freight.items.reduce(function (array, object) {
return array.concat(object[key]);
}, []);

Eloquent Javascript A list returns undefined , Why?

Task
A list
Objects, as generic blobs of values, can be used to build all sorts of data structures. A common data structure is the list (not to be confused with the array). A list is a nested set of objects, with the first object holding a reference to the second, the second to the third, and so on.
var list = {
value: 1,
rest: {
value: 2,
rest: {
value: 3,
rest: null
}
}
};
The resulting objects form a chain, like this:
A linked list
A nice thing about lists is that they can share parts of their structure. For example, if I create two new values {value: 0, rest: list} and {value: -1, rest: list} (with list referring to the variable defined earlier), they are both independent lists, but they share the structure that makes up their last three elements. In addition, the original list is also still a valid three-element list.
Write a function arrayToList that builds up a data structure like the previous one when given [1, 2, 3]
The over all goal is to create a function that creates a list structure as mentioned in the Exercise "A list" in the Data Structures Chapter.
function arrayToList(array){
var list = {};
var i = 0;
var rest = ((i < array.length) ? (i++,{value: array[i],rest: rest}): null) ;
list = {
value: array[0],
rest: rest
}
return list;
}
What I was hoping to accomplish was use the rest variable to call itself until the var i was greater than the array length, but when I run the code the rest property return undefined... my question is why does it not behave as recursive call to the same ternary var rest. I am fairly new to javascript so any advise or articles that would help me understand why this happens would be great.
You can use Array.prototype.reduce()
var list = {};
var arr = [1,2,3];
arr.reduce((o, prop, index, array) => {
o["value"] = prop;
o["rest"] = index < array.length -1 ? {} : null;
return o["rest"]
}, list);
console.log(list);
As commenters have said, you aren't actually making this function recursive - it never calls itself.
To achieve what you want you'd have to do this:
function arrayToList(array){
var list = {};
var rest = ((array.length) ? (arrayToList(array.slice(1))) : null) ;
list = {
value: array[0],
rest: rest
}
return list;
}
In modern javascript, you can simply do this:
var arrayToList = array => array.slice().reverse().reduce((rest, value) => ({ value, rest }), { rest:null });
which, after running it through a transpiler, becomes
var arrayToList = function arrayToList(array) {
return array.slice().reverse().reduce(function (rest, value) {
return { value: value, rest: rest };
}, { rest:null });
};
var array = [1,2,3,4,5];
var arrayToList = function(array) {
var list = {};
var array = array.reverse();
var arrLength = array.length;
for (var i = 0; i < arrLength; i++) {
var newList = function() {
if (i) {
return list;
} else {
return null
}
}
list = {
value: array[i],
list: newList()
}
}
return list;
}
console.log(arrayToList(array));
I also learn javascript from that book and i struggled with this one.
I think this is more close to what we have learned in the book so far.
Using reduce function is also a great way to resolve this , but it is not yet presented in the book and we presume we have no idea how to use it.

How do I remove objects from a JavaScript associative array?

Suppose I have this code:
var myArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;
Now if I wanted to remove "lastname"?....is there some equivalent of
myArray["lastname"].remove()?
(I need the element gone because the number of elements is important and I want to keep things clean.)
Objects in JavaScript can be thought of as associative arrays, mapping keys (properties) to values.
To remove a property from an object in JavaScript you use the delete operator:
const o = { lastName: 'foo' }
o.hasOwnProperty('lastName') // true
delete o['lastName']
o.hasOwnProperty('lastName') // false
Note that when delete is applied to an index property of an Array, you will create a sparsely populated array (ie. an array with a missing index).
When working with instances of Array, if you do not want to create a sparsely populated array - and you usually don't - then you should use Array#splice or Array#pop.
Note that the delete operator in JavaScript does not directly free memory. Its purpose is to remove properties from objects. Of course, if a property being deleted holds the only remaining reference to an object o, then o will subsequently be garbage collected in the normal way.
Using the delete operator can affect JavaScript engines' ability to optimise code.
All objects in JavaScript are implemented as hashtables/associative arrays. So, the following are the equivalent:
alert(myObj["SomeProperty"]);
alert(myObj.SomeProperty);
And, as already indicated, you "remove" a property from an object via the delete keyword, which you can use in two ways:
delete myObj["SomeProperty"];
delete myObj.SomeProperty;
Hope the extra info helps...
None of the previous answers address the fact that JavaScript does not have associative arrays to begin with - there is no array type as such, see typeof.
What JavaScript has, are object instances with dynamic properties. When properties are confused with elements of an Array object instance then Bad Things™ are bound to happen:
Problem
var elements = new Array()
elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]
console.log("number of elements: ", elements.length) // Returns 2
delete elements[1]
console.log("number of elements: ", elements.length) // Returns 2 (?!)
for (var i = 0; i < elements.length; i++)
{
// Uh-oh... throws a TypeError when i == 1
elements[i].onmouseover = function () { window.alert("Over It.")}
console.log("success at index: ", i)
}
Solution
To have a universal removal function that does not blow up on you, use:
Object.prototype.removeItem = function (key) {
if (!this.hasOwnProperty(key))
return
if (isNaN(parseInt(key)) || !(this instanceof Array))
delete this[key]
else
this.splice(key, 1)
};
//
// Code sample.
//
var elements = new Array()
elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]
console.log(elements.length) // Returns 2
elements.removeItem("prop")
elements.removeItem(0)
console.log(elements.hasOwnProperty("prop")) // Returns false as it should
console.log(elements.length) // returns 1 as it should
That only deletes the object, but it still keeps the array length the same.
To remove the element from the array, you need to do something like:
array.splice(index, 1);
While the accepted answer is correct, it is missing the explanation why it works.
First of all, your code should reflect the fact that this is not an array:
var myObject = new Object();
myObject["firstname"] = "Bob";
myObject["lastname"] = "Smith";
myObject["age"] = 25;
Note that all objects (including Arrays) can be used this way. However, do not expect for standard JavaScript array functions (pop, push, etc.) to work on objects!
As said in accepted answer, you can then use delete to remove the entries from objects:
delete myObject["lastname"]
You should decide which route you wish to take - either use objects (associative arrays / dictionaries) or use arrays (maps). Never mix the two of them.
There is an elegant way in the Airbnb Style Guide to do this (ECMAScript 7):
const myObject = {
a: 1,
b: 2,
c: 3
};
const { a, ...noA } = myObject;
console.log(noA); // => { b: 2, c: 3 }
Copyright: https://codeburst.io/use-es2015-object-rest-operator-to-omit-properties-38a3ecffe90
As other answers have noted, you are not using a JavaScript array, but a JavaScript object, which works almost like an associative array in other languages except that all keys are converted to strings. The new Map stores keys as their original type.
If you had an array and not an object, you could use the array's .filter function, to return a new array without the item you want removed:
var myArray = ['Bob', 'Smith', 25];
myArray = myArray.filter(function(item) {
return item !== 'Smith';
});
If you have an older browser and jQuery, jQuery has a $.grep method that works similarly:
myArray = $.grep(myArray, function(item) {
return item !== 'Smith';
});
Use method splice to completely remove an item from an object array:
Object.prototype.removeItem = function (key, value) {
if (value == undefined)
return;
for (var i in this) {
if (this[i][key] == value) {
this.splice(i, 1);
}
}
};
var collection = [
{ id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
{ id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
{ id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];
collection.removeItem("id", "87353080-8f49-46b9-9281-162a41ddb8df");
You are using Object, and you don't have an associative array to begin with. With an associative array, adding and removing items goes like this:
Array.prototype.contains = function(obj)
{
var i = this.length;
while (i--)
{
if (this[i] === obj)
{
return true;
}
}
return false;
}
Array.prototype.add = function(key, value)
{
if(this.contains(key))
this[key] = value;
else
{
this.push(key);
this[key] = value;
}
}
Array.prototype.remove = function(key)
{
for(var i = 0; i < this.length; ++i)
{
if(this[i] == key)
{
this.splice(i, 1);
return;
}
}
}
// Read a page's GET URL variables and return them as an associative array.
function getUrlVars()
{
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
function ForwardAndHideVariables() {
var dictParameters = getUrlVars();
dictParameters.add("mno", "pqr");
dictParameters.add("mno", "stfu");
dictParameters.remove("mno");
for(var i = 0; i < dictParameters.length; i++)
{
var key = dictParameters[i];
var value = dictParameters[key];
alert(key + "=" + value);
}
// And now forward with HTTP-POST
aa_post_to_url("Default.aspx", dictParameters);
}
function aa_post_to_url(path, params, method) {
method = method || "post";
var form = document.createElement("form");
// Move the submit function to another variable
// so that it doesn't get written over if a parameter name is 'submit'
form._submit_function_ = form.submit;
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var i = 0; i < params.length; i++)
{
var key = params[i];
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
document.body.appendChild(form);
form._submit_function_(); // Call the renamed function
}
If, for whatever reason, the delete key is not working (like it wasn't working for me), you can splice it out and then filter the undefined values:
// To cut out one element via arr.splice(indexToRemove, numberToRemove);
array.splice(key, 1)
array.filter(function(n){return n});
Don’t try and chain them since splice returns removed elements;
By using the "delete" keyword, it will delete the array element from array in JavaScript.
For example,
Consider following statements.
var arrayElementToDelete = new Object();
arrayElementToDelete["id"] = "XERTYB00G1";
arrayElementToDelete["first_name"] = "Employee_one";
arrayElementToDelete["status"] = "Active";
delete arrayElementToDelete["status"];
The last line of the code will remove the array element whose key is "status" from the array.
You can do the following if you want a more functional and elegant approach:
const o = { firstName: "foo", lastName: "bar" };
const { lastName, ...removed } = o;
lastName // bar
removed // { firstName: "foo" }
Note that the value of removed will be undefined if there are no items left in the object.
You can remove an entry from your map by explicitly assigning it to 'undefined'. As in your case:
myArray["lastname"] = undefined;
We can use it as a function too. Angular throws some error if used as a prototype. Thanks #HarpyWar. It helped me solve a problem.
var removeItem = function (object, key, value) {
if (value == undefined)
return;
for (var i in object) {
if (object[i][key] == value) {
object.splice(i, 1);
}
}
};
var collection = [
{ id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
{ id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
{ id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];
removeItem(collection, "id", "87353080-8f49-46b9-9281-162a41ddb8df");
It's very straightforward if you have an Underscore.js dependency in your project -
_.omit(myArray, "lastname")
The only working method for me:
function removeItem (array, value) {
var i = 0;
while (i < array.length) {
if(array[i] === value) {
array.splice(i, 1);
} else {
++i;
}
}
return array;
}
Usage:
var new = removeItem( ["apple","banana", "orange"], "apple");
// ---> ["banana", "orange"]
For "Arrays":
If you know the index:
array.splice(index, 1);
If you know the value:
function removeItem(array, value) {
var index = array.indexOf(value);
if (index > -1) {
array.splice(index, 1);
}
return array;
}
The most upvoted answer for delete works well in case of objects but not for the real arrays. If I use delete it removes elements from loops but keeps the element as empty and length of array wont change. This may be a problem in some scenarios.
For example, if I do myArray.toString() on myArray after removal via delete, it creates an empty entry, i.e. ,,.
var myArray = newmyArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;
var s = JSON.stringify(myArray);
s.replace(/"lastname[^,}]+,/g, '');
newmyArray = JSON.parse(p);
Without looping/iterates we get the same result.

Categories