I want to be able to match a specific string (full match not partial match) and then delete that specific item from the array if it matches.
I have some code but it doesn't seem to be deleting the item from the array. I do wish for it to change the original array and not create a new array so I am not using filter.
How can I go about accomplishing this?
Current Code:
let recentSearches = [
{ name: "Chicago, IL" },
{ name: "Orlando, FL" },
{ name: "Dallas, TX" }
];
let stringToRemove = "Dallas, TX";
recentSearches.some(recent => {
if (recent.name === stringToRemove) {
const index = recentSearches.indexOf(stringToRemove);
if (index !== -1) { //Never goes into this if
recentSearches.splice(index, 1);
console.log(recentSearches);
}
}
});
console.log(recentSearches);
JS Fiddle: enter link description here
If you don't mind the output being a different array, use filter:
const filteredSearches = recentSearches.filter((recent) => recent.name !== stringToRemove);
If you need to modify the array in-place, you should visit the elements in reverse order (in case of multiple matches, which causes indices to shift) like so:
for (let i = recentSearches.length-1; i >= 0; i--) {
if (recentSearches[i].name === stringToRemove) {
recentSearches.splice(i, 1);
}
}
The problem with your code is you use recentSearches.indexOf, but recentSearches isn't an array of strings, so nothing matches. You could modify your code as follows, but it won't work correctly in case of multiple mathces:
recentSearches.forEach((recent, index) => {
if (recent.name === stringToRemove) {
recentSearches.splice(index, 1);
}
});
Alternatively, you could use findIndex (as suggested in other comments and answers) as follows:
let index;
while (0 <= (index = recentSearches.findIndex((recent) => recent.name === stringToRemove)) {
recentSearches.splice(index, 1);
}
indexOf() is for finding exact matches. Since your array contains objects, they'll never be equal to stringToRemove.
Use findIndex() to get the index of an array element using a function that an compare the name property.
There's also no need for using some().
let recentSearches = [{
name: "Chicago, IL"
},
{
name: "Orlando, FL"
},
{
name: "Dallas, TX"
}
];
let stringToRemove = "Dallas, TX";
const index = recentSearches.findIndex(({
name
}) => name == stringToRemove);
if (index !== -1) { //Never goes into this if
recentSearches.splice(index, 1);
}
console.log(recentSearches);
Another version of the findIndex, instead of using while, you could use for, a slight advantage here is that the index is then locally scoped inside the the for, were with a while loop you have the extra scope of the index, you could close the the scope of a let by doing { let index; while() {..}} but the for loop avoids that without using {}.
let recentSearches = [
{name: "Chicago, IL"},
{name: "Orlando, FL"},
{name: "Dallas, TX"}
];
let stringToRemove = "Dallas, TX";
for (let index; index = recentSearches.findIndex(
search => search.name === stringToRemove), index > -1;)
recentSearches.splice(index, 1);
console.log(recentSearches);
The JSON search is done wrongly.
I have added the perfect code to complete your requirement. Find all instances and delete them with a while loop. This will ensure duplicate search terms are also removed if any.
let recentSearches = [
{name: "Chicago, IL"},
{name: "Orlando, FL"},
{name: "Dallas, TX"}
];
let stringToRemove = "Dallas, TX";
while (recentSearches.findIndex(search => search.name === stringToRemove) > -1) {
const index = recentSearches.findIndex(search => search.name === stringToRemove);
recentSearches.splice(index, 1);
}
console.log(recentSearches);
You can use findindex.
Store it in a variable.
And use splice
You can use this code:
Array.prototype._arraycopy = function(src, srcPos, dest, destPos, length) {
while ((--length) >= 0) {
dest[destPos++] = src[srcPos++];
}
};
Array.prototype._fastRemove = function(es, i) {
let newSize;
if ((newSize = this.length - 1) > i)
this._arraycopy(es, i + 1, es, i, newSize - i);
es[this.length = newSize] = null;
this.length = newSize;
}
Array.prototype.__removeAt = function(index) {
// Objects.checkIndex(index, size);
const es = this;
const oldValue =es[index];
this._fastRemove(es, index);
return oldValue;
}
Array.prototype.__removeAtValue = function(o) {
const es = this;
const size = this.size;
let i = 0;
(function() {
if (o == null) {
for (; i < size; i++)
if (es[i] == null)
return true;
} else {
for (; i < size; i++)
if (Object.is(o, es[i]))
return true;
}
return false;
})()
this._fastRemove(es, i);
return true;
}
Array.prototype.remove = function(index) {
return this.__removeAt(index)
}
Array.prototype.removeObj = function(obj) {
return this.__removeAtValue(obj);
}
const arr = [1, 3, 4, 5, 10];
console.log(arr);
const rem = arr.remove(1)
console.log({ arr, rem });
const objs = [{ id: 1, name: "Hello" }, { id: 2, name: "Arrow" }, { id: 3, name: "Star" }]
console.log(objs);
const deleted = objs.removeObj({ id: 2, name: "Arrow" });
console.log({ objs, deleted })
Related
I am trying to find the indexes of all the instances of an element, say, "Nano", in a JavaScript array.
var Cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];
I tried jQuery.inArray, or similarly, .indexOf(), but it only gave the index of the last instance of the element, i.e. 5 in this case.
How do I get it for all instances?
The .indexOf() method has an optional second parameter that specifies the index to start searching from, so you can call it in a loop to find all instances of a particular value:
function getAllIndexes(arr, val) {
var indexes = [], i = -1;
while ((i = arr.indexOf(val, i+1)) != -1){
indexes.push(i);
}
return indexes;
}
var indexes = getAllIndexes(Cars, "Nano");
You don't really make it clear how you want to use the indexes, so my function returns them as an array (or returns an empty array if the value isn't found), but you could do something else with the individual index values inside the loop.
UPDATE: As per VisioN's comment, a simple for loop would get the same job done more efficiently, and it is easier to understand and therefore easier to maintain:
function getAllIndexes(arr, val) {
var indexes = [], i;
for(i = 0; i < arr.length; i++)
if (arr[i] === val)
indexes.push(i);
return indexes;
}
Another alternative solution is to use Array.prototype.reduce():
["Nano","Volvo","BMW","Nano","VW","Nano"].reduce(function(a, e, i) {
if (e === 'Nano')
a.push(i);
return a;
}, []); // [0, 3, 5]
N.B.: Check the browser compatibility for reduce method and use polyfill if required.
Another approach using Array.prototype.map() and Array.prototype.filter():
var indices = array.map((e, i) => e === value ? i : '').filter(String)
More simple way with es6 style.
const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
//Examples:
var cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];
indexOfAll(cars, "Nano"); //[0, 3, 5]
indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]
indexOfAll([1, 2, 3], 4); // []
You can write a simple readable solution to this by using both map and filter:
const nanoIndexes = Cars
.map((car, i) => car === 'Nano' ? i : -1)
.filter(index => index !== -1);
EDIT: If you don't need to support IE/Edge (or are transpiling your code), ES2019 gave us flatMap, which lets you do this in a simple one-liner:
const nanoIndexes = Cars.flatMap((car, i) => car === 'Nano' ? i : []);
I just want to update with another easy method.
You can also use forEach method.
var Cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];
var result = [];
Cars.forEach((car, index) => car === 'Nano' ? result.push(index) : null)
Note: MDN gives a method using a while loop:
var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element = 'a';
var idx = array.indexOf(element);
while (idx != -1) {
indices.push(idx);
idx = array.indexOf(element, idx + 1);
}
I wouldn't say it's any better than other answers. Just interesting.
const indexes = cars
.map((car, i) => car === "Nano" ? i : null)
.filter(i => i !== null)
This worked for me:
let array1 = [5, 12, 8, 130, 44, 12, 45, 12, 56];
let numToFind = 12
let indexesOf12 = [] // the number whose occurrence in the array we want to find
array1.forEach(function(elem, index, array) {
if (elem === numToFind) {indexesOf12.push(index)}
return indexesOf12
})
console.log(indexesOf12) // outputs [1, 5, 7]
Just to share another method, you can use Function Generators to achieve the result as well:
function findAllIndexOf(target, needle) {
return [].concat(...(function*(){
for (var i = 0; i < target.length; i++) if (target[i] === needle) yield [i];
})());
}
var target = "hellooooo";
var target2 = ['w','o',1,3,'l','o'];
console.log(findAllIndexOf(target, 'o'));
console.log(findAllIndexOf(target2, 'o'));
["a", "b", "a", "b"]
.map((val, index) => ({ val, index }))
.filter(({val, index}) => val === "a")
.map(({val, index}) => index)
=> [0, 2]
You can use Polyfill
if (!Array.prototype.filterIndex)
{
Array.prototype.filterIndex = function (func, thisArg) {
'use strict';
if (!((typeof func === 'Function' || typeof func === 'function') && this))
throw new TypeError();
let len = this.length >>> 0,
res = new Array(len), // preallocate array
t = this, c = 0, i = -1;
let kValue;
if (thisArg === undefined) {
while (++i !== len) {
// checks to see if the key was set
if (i in this) {
kValue = t[i]; // in case t is changed in callback
if (func(t[i], i, t)) {
res[c++] = i;
}
}
}
}
else {
while (++i !== len) {
// checks to see if the key was set
if (i in this) {
kValue = t[i];
if (func.call(thisArg, t[i], i, t)) {
res[c++] = i;
}
}
}
}
res.length = c; // shrink down array to proper size
return res;
};
}
Use it like this:
[2,23,1,2,3,4,52,2].filterIndex(element => element === 2)
result: [0, 3, 7]
findIndex retrieves only the first index which matches callback output. You can implement your own findIndexes by extending Array , then casting your arrays to the new structure .
class EnhancedArray extends Array {
findIndexes(where) {
return this.reduce((a, e, i) => (where(e, i) ? a.concat(i) : a), []);
}
}
/*----Working with simple data structure (array of numbers) ---*/
//existing array
let myArray = [1, 3, 5, 5, 4, 5];
//cast it :
myArray = new EnhancedArray(...myArray);
//run
console.log(
myArray.findIndexes((e) => e===5)
)
/*----Working with Array of complex items structure-*/
let arr = [{name: 'Ahmed'}, {name: 'Rami'}, {name: 'Abdennour'}];
arr= new EnhancedArray(...arr);
console.log(
arr.findIndexes((o) => o.name.startsWith('A'))
)
We can use Stack and push "i" into the stack every time we encounter the condition "arr[i]==value"
Check this:
static void getindex(int arr[], int value)
{
Stack<Integer>st= new Stack<Integer>();
int n= arr.length;
for(int i=n-1; i>=0 ;i--)
{
if(arr[i]==value)
{
st.push(i);
}
}
while(!st.isEmpty())
{
System.out.println(st.peek()+" ");
st.pop();
}
}
When both parameter passed as array
function getIndexes(arr, val) {
var indexes = [], i;
for(i = 0; i < arr.length; i++){
for(j =0; j< val.length; j++) {
if (arr[i] === val[j])
indexes.push(i);
}
}
return indexes;
}
Also, findIndex() will be useful:
var cars = ['Nano', 'Volvo', 'BMW', 'Nano', 'VW', 'Nano'];
const indexes = [];
const searchedItem = 'NaNo';
cars.findIndex((value, index) => {
if (value.toLowerCase() === searchedItem.toLowerCase()) {
indexes.push(index);
}
});
console.log(indexes); //[ 0, 3, 5 ]
Bonus:
This custom solution using Object.entries() and forEach()
var cars = ['Nano', 'Volvo', 'BMW', 'Nano', 'VW', 'Nano'];
const indexes = [];
const searchableItem = 'Nano';
Object.entries(cars).forEach((item, index) => {
if (item[1].toLowerCase() === searchableItem.toLowerCase())
indexes.push(index);
});
console.log(indexes);
Note: I did not run run all tests
Let's assume that I have ;
var array = [1,2,3,4,4,5,5];
I want it to be;
var newArray = [1,2,3];
I want to remove the duplicates completely rather than keeping them as unique values. Is there a way achieve that through reduce method ?
You could use Array#filter with Array#indexOf and Array#lastIndexOf and return only the values which share the same index.
var array = [1, 2, 3, 4, 4, 5, 5],
result = array.filter(function (v, _, a) {
return a.indexOf(v) === a.lastIndexOf(v);
});
console.log(result);
Another approach by taking a Map and set the value to false, if a key has been seen before. Then filter the array by taking the value of the map.
var array = [1, 2, 3, 4, 4, 5, 5],
result = array.filter(
Map.prototype.get,
array.reduce((m, v) => m.set(v, !m.has(v)), new Map)
);
console.log(result);
I guess it won't have some remarkable performance, but I like the idea.
var array = [1,2,3,4,4,5,5],
res = array.reduce(function(s,a) {
if (array.filter(v => v !== a).length == array.length-1) {
s.push(a);
}
return s;
}, []);
console.log(res);
Another option is to use an object to track how many times an element is used. This will destroy the array order, but it should be much faster on very large arrays.
function nukeDuplications(arr) {
const hash = {};
arr.forEach(el => {
const qty = hash[el] || 0;
hash[el] = qty+1;
});
const ret = [];
Object.keys(hash).forEach(key => {
if (hash[key] === 1) {
ret.push(Number(key));
}
})
return ret;
}
var array = [1,2,3,4,4,5,5];
console.log(nukeDuplications(array));
A slightly more efficient solution would be to loop over the array 1 time and count the number of occurrences in each value and store them in an object using .reduce() and then loop over the array again with .filter() to only return items that occurred 1 time.
This method will also preserve the order of the array, as it merely uses the object keys as references - it does not iterate over them.
var array = [1,2,3,4,4,5,5];
var valueCounts = array.reduce((result, item) => {
if (!result[item]) {
result[item] = 0;
}
result[item]++;
return result;
}, {});
var unique = array.filter(function (elem) {
return !valueCounts[elem] || valueCounts[elem] <= 1;
});
console.log(unique)
Another option is to use an object to track how many times an element is used. This will destroy the array order, but it should be much faster on very large arrays.
// Both versions destroy array order.
// ES6 version
function nukeDuplications(arr) {
"use strict";
const hash = {};
arr.forEach(el => {
const qty = hash[el] || 0;
hash[el] = qty + 1;
});
const ret = [];
Object.keys(hash).forEach(key => {
if (hash[key] === 1) {
ret.push(Number(key));
}
})
return ret;
}
// ES5 version
function nukeDuplicationsEs5(arr) {
"use strict";
var hash = {};
for (var i = 0; i < arr.length; i++) {
var el = arr[i];
var qty = hash[el] || 0;
hash[el] = qty + 1;
};
var ret = [];
for (let key in hash) {
if (hash.hasOwnProperty(key)) {
if (hash[key] === 1) {
ret.push(Number(key));
}
}
}
return ret;
}
var array = [1, 2, 3, 4, 4, 5, 5];
console.log(nukeDuplications(array));
console.log(nukeDuplicationsEs5(array));
There are a lot of over-complicated, and slow running code here. Here's my solution:
let numbers = [1,2,3,4,4,4,4,5,5]
let filtered = []
numbers.map((n) => {
if(numbers.indexOf(n) === numbers.lastIndexOf(n)) // If only 1 instance of n
filtered.push(n)
})
console.log(filtered)
you can use this function:
function isUniqueInArray(array, value) {
let counter = 0;
for (let index = 0; index < array.length; index++) {
if (array[index] === value) {
counter++;
}
}
if (counter === 0) {
return null;
}
return counter === 1 ? true : false;
}
const array = [1,2,3,4,4,5,5];
let uniqueValues = [];
array.forEach(element => {
if(isUniqueInArray(array ,element)){
uniqueValues.push(element);
}
});
console.log(`the unique values is ${uniqueValues}`);
If its help you, you can install the isUniqueInArray function from my package https://www.npmjs.com/package/jotils or directly from bit https://bit.dev/joshk/jotils/is-unique-in-array.
My answer is used map and filter as below:
x = [1,2,3,4,2,3]
x.map(d => x.filter(i => i == d).length < 2 ? d : null).filter(d => d != null)
// [1, 4]
Object.values is supported since ES2017 (Needless to say - not on IE).
The accumulator is an object for which each key is a value, so duplicates are removed as they override the same key.
However, this solution can be risky with misbehaving values (null, undefined etc.), but maybe useful for real life scenarios.
let NukeDeps = (arr) => {
return Object.values(arr.reduce((curr, i) => {
curr[i] = i;
return curr;
}, {}))
}
I would like to answer my questions with an answer I came up with upon reading it again
const array = [1, 2, 3, 4, 4, 5, 5];
const filtered = array.filter(item => {
const { length } = array.filter(currentItem => currentItem === item)
if (length === 1) {
return true;
}
});
console.log(filtered)
//Try with this code
var arr = [1,2, 3,3,4,5,5,5,6,6];
arr = arr.filter( function( item, index, inputArray ) {
return inputArray.indexOf(item) == index;
});
Also look into this link https://fiddle.jshell.net/5hshjxvr/
Let's assume that I have ;
var array = [1,2,3,4,4,5,5];
I want it to be;
var newArray = [1,2,3];
I want to remove the duplicates completely rather than keeping them as unique values. Is there a way achieve that through reduce method ?
You could use Array#filter with Array#indexOf and Array#lastIndexOf and return only the values which share the same index.
var array = [1, 2, 3, 4, 4, 5, 5],
result = array.filter(function (v, _, a) {
return a.indexOf(v) === a.lastIndexOf(v);
});
console.log(result);
Another approach by taking a Map and set the value to false, if a key has been seen before. Then filter the array by taking the value of the map.
var array = [1, 2, 3, 4, 4, 5, 5],
result = array.filter(
Map.prototype.get,
array.reduce((m, v) => m.set(v, !m.has(v)), new Map)
);
console.log(result);
I guess it won't have some remarkable performance, but I like the idea.
var array = [1,2,3,4,4,5,5],
res = array.reduce(function(s,a) {
if (array.filter(v => v !== a).length == array.length-1) {
s.push(a);
}
return s;
}, []);
console.log(res);
Another option is to use an object to track how many times an element is used. This will destroy the array order, but it should be much faster on very large arrays.
function nukeDuplications(arr) {
const hash = {};
arr.forEach(el => {
const qty = hash[el] || 0;
hash[el] = qty+1;
});
const ret = [];
Object.keys(hash).forEach(key => {
if (hash[key] === 1) {
ret.push(Number(key));
}
})
return ret;
}
var array = [1,2,3,4,4,5,5];
console.log(nukeDuplications(array));
A slightly more efficient solution would be to loop over the array 1 time and count the number of occurrences in each value and store them in an object using .reduce() and then loop over the array again with .filter() to only return items that occurred 1 time.
This method will also preserve the order of the array, as it merely uses the object keys as references - it does not iterate over them.
var array = [1,2,3,4,4,5,5];
var valueCounts = array.reduce((result, item) => {
if (!result[item]) {
result[item] = 0;
}
result[item]++;
return result;
}, {});
var unique = array.filter(function (elem) {
return !valueCounts[elem] || valueCounts[elem] <= 1;
});
console.log(unique)
Another option is to use an object to track how many times an element is used. This will destroy the array order, but it should be much faster on very large arrays.
// Both versions destroy array order.
// ES6 version
function nukeDuplications(arr) {
"use strict";
const hash = {};
arr.forEach(el => {
const qty = hash[el] || 0;
hash[el] = qty + 1;
});
const ret = [];
Object.keys(hash).forEach(key => {
if (hash[key] === 1) {
ret.push(Number(key));
}
})
return ret;
}
// ES5 version
function nukeDuplicationsEs5(arr) {
"use strict";
var hash = {};
for (var i = 0; i < arr.length; i++) {
var el = arr[i];
var qty = hash[el] || 0;
hash[el] = qty + 1;
};
var ret = [];
for (let key in hash) {
if (hash.hasOwnProperty(key)) {
if (hash[key] === 1) {
ret.push(Number(key));
}
}
}
return ret;
}
var array = [1, 2, 3, 4, 4, 5, 5];
console.log(nukeDuplications(array));
console.log(nukeDuplicationsEs5(array));
There are a lot of over-complicated, and slow running code here. Here's my solution:
let numbers = [1,2,3,4,4,4,4,5,5]
let filtered = []
numbers.map((n) => {
if(numbers.indexOf(n) === numbers.lastIndexOf(n)) // If only 1 instance of n
filtered.push(n)
})
console.log(filtered)
you can use this function:
function isUniqueInArray(array, value) {
let counter = 0;
for (let index = 0; index < array.length; index++) {
if (array[index] === value) {
counter++;
}
}
if (counter === 0) {
return null;
}
return counter === 1 ? true : false;
}
const array = [1,2,3,4,4,5,5];
let uniqueValues = [];
array.forEach(element => {
if(isUniqueInArray(array ,element)){
uniqueValues.push(element);
}
});
console.log(`the unique values is ${uniqueValues}`);
If its help you, you can install the isUniqueInArray function from my package https://www.npmjs.com/package/jotils or directly from bit https://bit.dev/joshk/jotils/is-unique-in-array.
My answer is used map and filter as below:
x = [1,2,3,4,2,3]
x.map(d => x.filter(i => i == d).length < 2 ? d : null).filter(d => d != null)
// [1, 4]
Object.values is supported since ES2017 (Needless to say - not on IE).
The accumulator is an object for which each key is a value, so duplicates are removed as they override the same key.
However, this solution can be risky with misbehaving values (null, undefined etc.), but maybe useful for real life scenarios.
let NukeDeps = (arr) => {
return Object.values(arr.reduce((curr, i) => {
curr[i] = i;
return curr;
}, {}))
}
I would like to answer my questions with an answer I came up with upon reading it again
const array = [1, 2, 3, 4, 4, 5, 5];
const filtered = array.filter(item => {
const { length } = array.filter(currentItem => currentItem === item)
if (length === 1) {
return true;
}
});
console.log(filtered)
//Try with this code
var arr = [1,2, 3,3,4,5,5,5,6,6];
arr = arr.filter( function( item, index, inputArray ) {
return inputArray.indexOf(item) == index;
});
Also look into this link https://fiddle.jshell.net/5hshjxvr/
In my array of objects, I want to find the object with the highest value for the id property.
Here is my array:
myArray = [
{
'id': '73',
'foo': 'bar'
},
{
'id': '45',
'foo': 'bar'
},
// …
];
Generally, I use $.grep to find values in an array, like this:
var result = $.grep(myArray, function (e) {
return e.id == 73;
});
But in this case I need to provide a specific id value for the object I want to select.
The question states that he wants to find the object with the greatest id, not just the greatest id...
var myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
var max = myArray.reduce(function(prev, current) {
if (+current.id > +prev.id) {
return current;
} else {
return prev;
}
});
// max == {'id':'73','foo':'bar'}
const students = [
{ id: 100, name: 'Abolfazl', family: 'Roshanzamir' },
{ id: 2, name: 'Andy', family: 'Madadian' },
{ id: 1500, name: 'Kouros', family: 'Shahmir' }
]
If you want to find the object with max Id :
const item = students.reduce((prev, current) => (+prev.id > +current.id) ? prev : current)
// it returns { id: 1500, name: 'Kouros', family: 'Shahmir' }
If you want to find the object with min Id :
const item = students.reduce((prev, current) => (+prev.id < +current.id) ? prev : current)
// it returns {id: 2, name: "Andy", family: "Madadian"}
If you wnat to find the max Id :
const max = Math.max.apply(null, students.map(item => item.id));
// it returns 1500
If you want to find the min Id :
const min = Math.min.apply(null, students.map(item => item.id));
// it returns 2
Use the map() method of the array. Using map you can provide a function that iterates over every element in the array. In that function, you can work out the object with the highest id. For example:
myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
var maxid = 0;
myArray.map(function(obj){
if (obj.id > maxid) maxid = obj.id;
});
This will give you the max id of the objects in the array.
Then you can use grep to get the related object:
var maxObj = $.grep(myArray, function(e){ return e.id == maxid; });
Alternatively, if you just want the object with the max id, you can do this:
var maxid = 0;
var maxobj;
myArray.map(function(obj){
if (obj.id > maxid) maxobj = obj;
});
//maxobj stores the object with the max id.
var max = 0;
var myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}]
var maxEle = myArray.map(function(ele){ if(ele.id>max){ max=ele} });
map is a function which iterates through array elements and performs specific operation.
let id = items.reduce((maxId, item) => Math.max(maxId, item.id), 0);
or
let id = Math.max(...items.map(item => item.id).concat(0)); // concat(0) for empty array
// slimmer and sleeker ;)
let id = Math.max(...items.map(item => item.id), 0);
This way is more practical, because in the case of an empty array, it returns 0, unlike
Math.max.apply(null, [].map(item => item.id)) // -Infinity
and if you want to get "autoincrement", you can just add 1 regardless of whether the array is empty or not
// starts at 1 if our array is empty
autoincrement = items.reduce((maxId, item) => Math.max(maxId, item.id), 0) + 1;
UPD: Code with map is shorter but with reduce is faster, which is felt with large arrays
let items = Array(100000).fill()
.map((el, _, arr) => ({id: ~~(Math.random() * arr.length), name: 'Summer'}));
const n = 100;
console.time('reduce test');
for (let i = 1; i < n; ++i) {
let id = items.reduce((maxId, item) => Math.max(maxId, item.id), 0);
}
console.timeEnd('reduce test');
console.time('map test');
for (let i = 1; i < n; ++i) {
let id = Math.max(items.map(item => item.id).concat(0));
}
console.timeEnd('map test');
console.time('map spread test');
for (let i = 1; i < n; ++i) {
let id = Math.max(...items.map(item => item.id), 0);
}
console.timeEnd('map spread test');
reduce test: 163.373046875ms
map test: 1282.745849609375ms
map spread test: 242.4111328125ms
If we create an even larger array, spread map will shutdown
let items = Array(200000).fill()
.map((el, _, arr) => ({id: ~~(Math.random() * arr.length), name: 'Summer'}));
reduce test: 312.43896484375ms
map test: 2941.87109375ms
Uncaught RangeError: Maximum call stack size exceeded
at :15:32
function reduceBy(reducer, acc) {
return function(by, arr) {
return arr[arr.reduce(function(acc, v, i) {
var b = by(v);
return reducer(acc[0], b) ? [b, i] : acc;
}, acc || [by(arr[0]), 0])[1]];
};
}
var maximumBy = reduceBy(function(a,b){return a<b;});
var myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
console.log(maximumBy(function(x){
return parseInt(x.id,10)
}, myArray)); // {'id':'73','foo':'bar'}
a shorten version using reduce()
myArray.reduce((max, cur)=>(max.likes>cur.likes?max:cur))
If I have something like
[Object(id:03235252, name:"streetAddress"), Object(id:32624666, name:"zipCode")...]
How can I remove an object from that array that has name set to "zipCode"?
If you need to modify the existing Array, you should use splice().
for (var i = array.length - 1; i > -1; i--) {
if (array[i].name === "zipCode")
array.splice(i, 1);
}
Notice that I'm looping in reverse. This is in order to deal with the fact that when you do a .splice(i, 1), the array will be reindexed.
If we did a forward loop, we would also need to adjust i whenever we do a .splice() in order to avoid skipping an index.
arr = arr.filter(function (item) {
return (item.name !== 'zipCode');
});
Updated suggestion
Updated this answer due to doing prototypes on arrays are bad prac so to get people who use the suggestion to write better code here is a better option:
const myArr = [
{
name: "lars",
age: 25
}, {
name: "hugo",
age: 28
}, {
name: "bent",
age: 24
}, {
name: "jimmy",
age: 22
}
];
const findAndRemove = (array, prop, value) => {
return array.filter((item) => item[prop] !== value);
}
const newArr = findAndRemove(myArr, 'name', 'jimmy')
console.log(newArr)
// Could also be simply written like this:
const otherArr = myArr.filter(item => item.name !== 'jimmy')
New code can be found and tested here
Old suggestion
This can also be done with a prototype on the array
Array.prototype.containsByProp = function(propName, value){
for (var i = this.length - 1; i > -1; i--) {
var propObj = this[i];
if(propObj[propName] === value) {
return true;
}
}
return false;
}
var myArr = [
{
name: "lars",
age: 25
}, {
name: "hugo",
age: 28
}, {
name: "bent",
age: 24
}, {
name: "jimmy",
age: 22
}
];
console.log(myArr.containsByProp("name", "brent")); // Returns false
console.log(myArr.containsByProp("name", "bent")); // Returns true
Code can also be found and tested here
var i = array.length;
while(i-- > 0) {
if (array[i].name === "zipCode")
array.splice(i, 1);
}
Loop through the array backwards (so you won't have to skip indexes when splicing)
Check each item's name if it's "zipCode"
If it is, splice it off using yourArray.splice(index,1);
Then either:
continue if there is a possibility of having more than one name having the value "zipCode"
break the loop
This may be a detailed and easy solution.
//plain array
var arr = ['a', 'b', 'c'];
var check = arr.includes('a');
console.log(check); //returns true
if (check)
{
// value exists in array
//write some codes
}
// array with objects
var arr = [
{x:'a', y:'b'},
{x:'p', y:'q'}
];
// if you want to check if x:'p' exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p')
{
return elm; // returns length = 1 (object exists in array)
}
});
// or y:'q' exists in arr
var check = arr.filter(function (elm){
if (elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// if you want to check, if the entire object {x:'p', y:'q'} exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p' && elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// in all cases
console.log(check.length); // returns 1
if (check.length > 0)
{
// returns true
// object exists in array
//write some codes
}