Extract strings with unique characters from javascript Array - javascript

I want to extract only those strings which have unique characters, I have an array of strings:
var arr = ["abb", "abc", "abcdb", "aea", "bbb", "ego"];
Output: ["abc", "ego"]
I tried to achieve it using Array.forEach() method:
var arr = ["abb", "abc", "abcdb", "aea", "bbb", "ego"];
const filterUnique = (arr) => {
var result = [];
arr.forEach(element => {
for (let i = 0; i <= element.length; i++) {
var a = element[i];
if (element.indexOf(a, i + 1) > -1) {
return false;
}
}
result.push(element);
});
return result;
}
console.log(filterUnique(arr));
Want to know is any other way to achieve this task ?
Any suggestion.

I'd .filter by whether the size of a Set of the string is the same as the length of the string:
const filterUnique = arr => arr
.filter(str => new Set(str).size === str.length);
console.log(filterUnique(["abb", "abc", "abcdb", "aea", "bbb", "ego"]));
(a Set will not hold duplicate elements, so, eg, if 4 elements are put into a set and 2 are duplicates of others, the resulting size of the Set will be 2)

You can check by creating sets from strings also, a Set object will always have unique values.
var a = ["abb", "abc", "abcdb", "aea", "bbb", "ego"];
console.log(a.filter(v => v.length === new Set(v).size))

Related

How can I delete duplicated values in an array while counting the repetitions?

I would like to count the amount of times that a value appears in an array, and delete the repeated values keeping just the first.
So I can store in another array the amount of times that it appears, and it will have the same index as the value in the other array.
The loops I have tried don't count the amount of times correctly or delete other values that shouldn't be the ones deleted.
var itemCount = [];
var itemsName = ["aaa", "bbb", "aaa", "ccc", "ddd", "ddd"]
for (let index = 0; index < itemsName.length; index++) {
for (var i = index + 1; i < itemsName.length; ++i) {
itemCount[index] = 1
if (itemsName[i] === itemsName[index]){
itemCount[index]++;
itemsName.splice(i, 1)
}
}
if (itemCount[index] > 1) {
console.log(itemsName[index] + itemCount[index])
} else {
console.log(itemsName[index])
}
}
So the output should be like,
aaa3 bbb ccc ddd2
I made some changes to your code
const itemsName = ["aaa", "bbb", "aaa", "ccc", "ddd", "ddd"];
const itemCount = {}; // It's better to set this as an object.
for (let index = 0; index < itemsName.length; index++) {
// index is a key and not the value of the array.
// itemsName[index] will give you the value of an item in the array
// Here I check if the key exists, incrementing it or setting it to 1.
if (itemCount[itemsName[index]]) itemCount[itemsName[index]]++;
else itemCount[itemsName[index]] = 1;
}
for (let key in itemCount) {
console.log(key + itemCount[key]);
}
If you remove an entry from an array you change the index of subsequent entries. Thus you cannot keep the old index in the new array you create for duplicates.
What you can do is create two separate arrays, one without duplicates, the other containing objects with the duplicates and their index.
var itemsName = [...];
var newArray = [];
var duplicatesArray = [];
var duplicateCount = 0;
// map creates a new array with the return statement
newArray = itemsName.map((entry,index) => {
// check if the new array includes the current entry iteration
if ( newArray.inculdes(entry) ) {
duplicateCount++; // just the duplicate counter
let duplicate = { oldIndex: index, value: entry }; // duplicate entry containing the oldIndex well .. index. This is so that you can get the index of the entry in the old array.
duplicatesArray.push(duplicate); // add entry to duplicateArray
return; // finish iteration without adding the entry to the new array
}
return e; // add iteration entry to the new array
});
This should be it. =)
Instead of using an array to keep track of the item count, use an object instead. You can use the item name as object key to quickly find the current count and increment it.
const itemsName = ["aaa", "bbb", "aaa", "ccc", "ddd", "ddd", "1", 1];
const itemCount = {};
for (const name of itemsName) {
itemCount[name] ||= 0;
itemCount[name] += 1;
}
console.log("unique values", Object.keys(itemCount));
console.log("itemCount", itemCount);
||= is a fairly new operator, if you are not using a transpiler (like Babel) to support older browsers you might want to use the following instead:
if (!itemCount[name]) itemCount[name] = 0;
Note that when using objects the all keys are converted to strings. So "1" and 1 are considered the same. If you want to differentiate between strings, numbers, complex objects (by identity, not value), etc. use a Map instead.
const itemsName = ["aaa", "bbb", "aaa", "ccc", "ddd", "ddd", "1", 1];
const itemCount = new Map();
for (const name of itemsName) {
if (!itemCount.has(name)) itemCount.set(name, 0);
itemCount.set(name, itemCount.get(name) + 1);
}
console.log("unique values", Array.from(itemCount.keys()));
for (const [name, count] of itemCount) {
console.log(typeof name, name, count);
}

How to Remove Value from Object Key

I have an array of objects called active_filters. It contains a key called value which can contain one or more values (which are separated by commas if there are multiples). I'm trying to remove a certain code from the value key using findIndex. I'm not sure what I'm doing wrong...would appreciate any help. Thanks!
remove_code = "SFMR";
active_filters[0] = {id: "data-type", value: "SFAR,CFAR,IFAR,SFMR,FFAR,PDAR,MCMR,EDMR,CDMR,ECMR,EDAR,CDAR,MDMR", type: "filtered-out-by-car-type"};
Code:
var index = active_filters.findIndex(function(e) { return e.value.split(",").indexOf(remove_code) && e.id === _id });
if (index > -1)
active_filters.splice(index, 1);
Iterate the array with [Array.findIndex()][1] to find the element by id. If the element was found, split the value by comma. Use Array.filter() to remove the code, and join back. Assign the result back to the value property.
var remove_code = "SFMR";
var _id = 'data-type';
var active_filters = [{id: "data-type", value: "SFAR,CFAR,IFAR,SFMR,FFAR,PDAR,MCMR,EDMR,CDMR,ECMR,EDAR,CDAR,MDMR", type: "filtered-out-by-car-type"}];
var index = active_filters.findIndex(function(o) {
return o.id === _id;
});
if(index !== -1) {
active_filters[index].value = active_filters[index].value.split(',').filter(function(s) {
return s !== remove_code;
}).join();
}
console.log(active_filters);
You can do the following with filter(), map(), indexOf() and splice():
var remove_code = "SFMR";
var _id = "data-type";
var active_filters = [{id: "data-type", value: "SFAR,CFAR,IFAR,SFMR,FFAR,PDAR,MCMR,EDMR,CDMR,ECMR,EDAR,CDAR,MDMR", type: "filtered-out-by-car-type"}];
var active_filters = active_filters.filter(i => i.id==_id).map(function(e) {
var temp = e.value.split(",");
var index = temp.indexOf(remove_code);
temp.splice(index,1);
e.value = temp.join();
return e;
});
console.log(active_filters);
You could find the index the slice around it and set that to the value. Create a function that takes in the characters that you want to remove then find the index of those characters. After that you can slice from 0 to the specified index, then from the index + 5 (5 to include the comma) to finish out the remainder of the string. Here's an example of that:
const remove_code = "SFMR";
let active_filters = [];
active_filters.push({id: "data-type", value: "SFAR,CFAR,IFAR,SFMR,FFAR,PDAR,MCMR,EDMR,CDMR,ECMR,EDAR,CDAR,MDMR", type: "filtered-out-by-car-type"});
function removeChars(chars){
const index = active_filters[0].value.indexOf(remove_code);
let newString;
newString = active_filters[0].value.slice(0, index);
newString += active_filters[0].value.slice(index+5);
return newString;
}
active_filters[0].value = removeChars(remove_code);
console.log(active_filters[0]);
I'm trying to remove a certain code from the value key using findIndex.
You're splicing the entire array active_filters, what you need to do is split the filter's value and splice it according the remove_code values. To accomplish that, make a reverse loop and for each match execute the function splice.
Finally, join the values again separating them with comma.
var remove_code = "SFMR",
_id = 'data-type',
active_filters = [{id: "data-type", value: "SFAR,CFAR,IFAR,SFMR,FFAR,PDAR,MCMR,EDMR,CDMR,ECMR,EDAR,CDAR,MDMR", type: "filtered-out-by-car-type"}];
active_filters.forEach(function(f) {
if (f.id === _id) {
var values = f.value.split(','),
length = values.length;
while (length--) if (values[length] === remove_code) values.splice(length, 1);
f.value = values.join();
}
});
console.log(active_filters);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://codepen.io/egomezr/pen/dmLLwP.js"></script>

Convert set of object's into array item

I have several objects like this:
{'id[0]': 2}
{'url[0]': 11}
{'id[1]': 3}
{'url[1]': 14}
And I want to get something like this:
[{id:2, url:11}, {id:3, url:14}]
Also I have lodash in my project. Maybe lodash have some method for this?
You could use a regular expression for the keys and create a new object if necessary. Then assign the value to the key.
var data = [{ 'id[0]': 2 }, { 'url[0]': 11 }, { 'id[1]': 3 }, { 'url[1]': 14 }],
result = [];
data.forEach(function (a) {
Object.keys(a).forEach(function (k) {
var keys = k.match(/^([^\[]+)\[(\d+)\]$/);
if (keys.length === 3) {
result[keys[2]] = result[keys[2]] || {};
result[keys[2]][keys[1]] = a[k];
}
});
});
console.log(result);
This is an ES6 solution based on #NinaScholz solution.
I assume that the objects have only one property each, like the ones presented in the question.
Combine the array of objects to one large object using Object#assign, and convert to entries with Object.entries.
Iterate the array using Array#reduce.
Extract the original key an value from each entry using array
destructuring.
Extract the wanted key and index using a regex and array
destructuring.
Then create/update the new object at the index using object spread.
const data = [{ 'id[0]': 2 }, { 'url[0]': 11 }, { 'id[1]': 3 }, { 'url[1]': 14 }];
// combine to one object, and convert to entries
const result = Object.entries(Object.assign({}, ...data))
// extract the original key and value
.reduce((r, [k, value]) => {
// extract the key and index while ignoring the full match
const [, key, index] = k.match(/^([^\[]+)\[(\d+)\]$/);
// create/update the object at the index
r[index] = {...(r[index] || {}), [key]: value };
return r;
}, []);
console.log(result);
var arr = [{'id[0]': 2},
{'url[0]': 11},
{'id[1]': 3},
{'url[1]': 14}];
var result = [];
arr.forEach(function(e, i, a){
var index = +Object.keys(e)[0].split('[')[1].split(']')[0];//get the number inside []
result[index] = result[index] || {}; //if item is undefined make it empty object
result[index][Object.keys(e)[0].split('[')[0]] = e[Object.keys(e)[0]];//add item to object
})
console.log(result);
You can use for loop, .filter(), RegExp constructor with parameter "\["+i+"\]" where i is current index, Object.keys(), .reduce(), .replace() with RegExp /\[\d+\]/
var obj = [{
"id[0]": 2
}, {
"url[0]": 11
}, {
"id[1]": 3
}, {
"url[1]": 14
}];
var res = [];
for (var i = 0; i < obj.length / 2; i++) {
res[i] = obj.filter(function(o) {
return new RegExp("\[" + i + "\]").test(Object.keys(o))
})
.reduce(function(obj, o) {
var key = Object.keys(o).pop();
obj[key.replace(/\[\d+\]/, "")] = o[key];
return obj
}, {})
}
console.log(res);

Delete an object within an array, within another array [duplicate]

var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
How do I remove an object from the array by matching object property?
Only native JavaScript please.
I am having trouble using splice because length diminishes with each deletion.
Using clone and splicing on orignal index still leaves you with the problem of diminishing length.
I assume you used splice something like this?
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
}
}
All you need to do to fix the bug is decrement i for the next time around, then (and looping backwards is also an option):
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
i--;
}
}
To avoid linear-time deletions, you can write array elements you want to keep over the array:
var end = 0;
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) === -1) {
arrayOfObjects[end++] = obj;
}
}
arrayOfObjects.length = end;
and to avoid linear-time lookups in a modern runtime, you can use a hash set:
const setToDelete = new Set(listToDelete);
let end = 0;
for (let i = 0; i < arrayOfObjects.length; i++) {
const obj = arrayOfObjects[i];
if (setToDelete.has(obj.id)) {
arrayOfObjects[end++] = obj;
}
}
arrayOfObjects.length = end;
which can be wrapped up in a nice function:
const filterInPlace = (array, predicate) => {
let end = 0;
for (let i = 0; i < array.length; i++) {
const obj = array[i];
if (predicate(obj)) {
array[end++] = obj;
}
}
array.length = end;
};
const toDelete = new Set(['abc', 'efg']);
const arrayOfObjects = [{id: 'abc', name: 'oh'},
{id: 'efg', name: 'em'},
{id: 'hij', name: 'ge'}];
filterInPlace(arrayOfObjects, obj => !toDelete.has(obj.id));
console.log(arrayOfObjects);
If you don’t need to do it in place, that’s Array#filter:
const toDelete = new Set(['abc', 'efg']);
const newArray = arrayOfObjects.filter(obj => !toDelete.has(obj.id));
You can remove an item by one of its properties without using any 3rd party libs like this:
var removeIndex = array.map(item => item.id).indexOf("abc");
~removeIndex && array.splice(removeIndex, 1);
With lodash/underscore:
If you want to modify the existing array itself, then we have to use splice. Here is the little better/readable way using findWhere of underscore/lodash:
var items= [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'},
{id:'hij',name:'ge'}];
items.splice(_.indexOf(items, _.findWhere(items, { id : "abc"})), 1);
With ES5 or higher
(without lodash/underscore)
With ES5 onwards we have findIndex method on array, so its easier without lodash/underscore
items.splice(items.findIndex(function(i){
return i.id === "abc";
}), 1);
(ES5 is supported in almost all morden browsers)
About findIndex, and its Browser compatibility
To delete an object by it's id in given array;
const hero = [{'id' : 1, 'name' : 'hero1'}, {'id': 2, 'name' : 'hero2'}];
//remove hero1
const updatedHero = hero.filter(item => item.id !== 1);
findIndex works for modern browsers:
var myArr = [{id:'a'},{id:'myid'},{id:'c'}];
var index = myArr.findIndex(function(o){
return o.id === 'myid';
})
if (index !== -1) myArr.splice(index, 1);
Check this out using Set and ES5 filter.
let result = arrayOfObjects.filter( el => (-1 == listToDelete.indexOf(el.id)) );
console.log(result);
Here is JsFiddle:
https://jsfiddle.net/jsq0a0p1/1/
If you just want to remove it from the existing array and not create a new one, try:
var items = [{Id: 1},{Id: 2},{Id: 3}];
items.splice(_.indexOf(items, _.find(items, function (item) { return item.Id === 2; })), 1);
Loop in reverse by decrementing i to avoid the problem:
for (var i = arrayOfObjects.length - 1; i >= 0; i--) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
}
}
Or use filter:
var newArray = arrayOfObjects.filter(function(obj) {
return listToDelete.indexOf(obj.id) === -1;
});
Only native JavaScript please.
As an alternative, more "functional" solution, working on ECMAScript 5, you could use:
var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}]; // all that should remain
arrayOfObjects.reduceRight(function(acc, obj, idx) {
if (listToDelete.indexOf(obj.id) > -1)
arrayOfObjects.splice(idx,1);
}, 0); // initial value set to avoid issues with the first item and
// when the array is empty.
console.log(arrayOfObjects);
[ { id: 'hij', name: 'ge' } ]
According to the definition of 'Array.prototype.reduceRight' in ECMA-262:
reduceRight does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn.
So this is a valid usage of reduceRight.
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
as per your answer will be like this. when you click some particular object send the index in the param for the delete me function. This simple code will work like charm.
function deleteme(i){
if (i > -1) {
arrayOfObjects.splice(i, 1);
}
}
If you like short and self descriptive parameters or if you don't want to use splice and go with a straight forward filter or if you are simply a SQL person like me:
function removeFromArrayOfHash(p_array_of_hash, p_key, p_value_to_remove){
return p_array_of_hash.filter((l_cur_row) => {return l_cur_row[p_key] != p_value_to_remove});
}
And a sample usage:
l_test_arr =
[
{
post_id: 1,
post_content: "Hey I am the first hash with id 1"
},
{
post_id: 2,
post_content: "This is item 2"
},
{
post_id: 1,
post_content: "And I am the second hash with id 1"
},
{
post_id: 3,
post_content: "This is item 3"
},
];
l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 2); // gives both of the post_id 1 hashes and the post_id 3
l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 1); // gives only post_id 3 (since 1 was removed in previous line)
with filter & indexOf
withLodash = _.filter(arrayOfObjects, (obj) => (listToDelete.indexOf(obj.id) === -1));
withoutLodash = arrayOfObjects.filter(obj => listToDelete.indexOf(obj.id) === -1);
with filter & includes
withLodash = _.filter(arrayOfObjects, (obj) => (!listToDelete.includes(obj.id)))
withoutLodash = arrayOfObjects.filter(obj => !listToDelete.includes(obj.id));
You can use filter. This method always returns the element if the condition is true. So if you want to remove by id you must keep all the element that doesn't match with the given id. Here is an example:
arrayOfObjects = arrayOfObjects.filter(obj => obj.id != idToRemove)
Incorrect way
First of all, any answer that suggests to use filter does not actually remove the item. Here is a quick test:
var numbers = [1, 2, 2, 3];
numbers.filter(x => x === 2);
console.log(numbers.length);
In the above, the numbers array will stay intact (nothing will be removed). The filter method returns a new array with all the elements that satisfy the condition x === 2 but the original array is left intact.
Sure you can do this:
var numbers = [1, 2, 2, 3];
numbers = numbers.filter(x => x === 2);
console.log(numbers.length);
But that is simply assigning a new array to numbers.
Correct way to remove items from array
One of the correct ways, there are more than 1, is to do it as following. Please keep in mind, the example here intentionally has duplicated items so the removal of duplicates can be taken into consideration.
var numbers = [1, 2, 2, 3];
// Find all items you wish to remove
// If array has objects, then change condition to x.someProperty === someValue
var numbersToRemove = numbers.filter(x => x === 2);
// Now remove them
numbersToRemove.forEach(x => numbers.splice(numbers.findIndex(n => n === x), 1));
// Now check (this is obviously just to test)
console.log(numbers.length);
console.log(numbers);
Now you will notice length returns 2 indicating only numbers 1 and 3 are remaining in the array.
In your case
To specifically answer your question which is this:
var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
Here is the answer:
listToDelete.forEach(x => arrayOfObjects.splice(arrayOfObjects.findIndex(n => n.id === x), 1));
var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
var result = arrayOfObjects.filter(object => !listToDelete.some(toDelete => toDelete === object.id));
console.log(result);

remove objects from array by object property

var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
How do I remove an object from the array by matching object property?
Only native JavaScript please.
I am having trouble using splice because length diminishes with each deletion.
Using clone and splicing on orignal index still leaves you with the problem of diminishing length.
I assume you used splice something like this?
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
}
}
All you need to do to fix the bug is decrement i for the next time around, then (and looping backwards is also an option):
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
i--;
}
}
To avoid linear-time deletions, you can write array elements you want to keep over the array:
var end = 0;
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) === -1) {
arrayOfObjects[end++] = obj;
}
}
arrayOfObjects.length = end;
and to avoid linear-time lookups in a modern runtime, you can use a hash set:
const setToDelete = new Set(listToDelete);
let end = 0;
for (let i = 0; i < arrayOfObjects.length; i++) {
const obj = arrayOfObjects[i];
if (setToDelete.has(obj.id)) {
arrayOfObjects[end++] = obj;
}
}
arrayOfObjects.length = end;
which can be wrapped up in a nice function:
const filterInPlace = (array, predicate) => {
let end = 0;
for (let i = 0; i < array.length; i++) {
const obj = array[i];
if (predicate(obj)) {
array[end++] = obj;
}
}
array.length = end;
};
const toDelete = new Set(['abc', 'efg']);
const arrayOfObjects = [{id: 'abc', name: 'oh'},
{id: 'efg', name: 'em'},
{id: 'hij', name: 'ge'}];
filterInPlace(arrayOfObjects, obj => !toDelete.has(obj.id));
console.log(arrayOfObjects);
If you don’t need to do it in place, that’s Array#filter:
const toDelete = new Set(['abc', 'efg']);
const newArray = arrayOfObjects.filter(obj => !toDelete.has(obj.id));
You can remove an item by one of its properties without using any 3rd party libs like this:
var removeIndex = array.map(item => item.id).indexOf("abc");
~removeIndex && array.splice(removeIndex, 1);
With lodash/underscore:
If you want to modify the existing array itself, then we have to use splice. Here is the little better/readable way using findWhere of underscore/lodash:
var items= [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'},
{id:'hij',name:'ge'}];
items.splice(_.indexOf(items, _.findWhere(items, { id : "abc"})), 1);
With ES5 or higher
(without lodash/underscore)
With ES5 onwards we have findIndex method on array, so its easier without lodash/underscore
items.splice(items.findIndex(function(i){
return i.id === "abc";
}), 1);
(ES5 is supported in almost all morden browsers)
About findIndex, and its Browser compatibility
To delete an object by it's id in given array;
const hero = [{'id' : 1, 'name' : 'hero1'}, {'id': 2, 'name' : 'hero2'}];
//remove hero1
const updatedHero = hero.filter(item => item.id !== 1);
findIndex works for modern browsers:
var myArr = [{id:'a'},{id:'myid'},{id:'c'}];
var index = myArr.findIndex(function(o){
return o.id === 'myid';
})
if (index !== -1) myArr.splice(index, 1);
Check this out using Set and ES5 filter.
let result = arrayOfObjects.filter( el => (-1 == listToDelete.indexOf(el.id)) );
console.log(result);
Here is JsFiddle:
https://jsfiddle.net/jsq0a0p1/1/
If you just want to remove it from the existing array and not create a new one, try:
var items = [{Id: 1},{Id: 2},{Id: 3}];
items.splice(_.indexOf(items, _.find(items, function (item) { return item.Id === 2; })), 1);
Loop in reverse by decrementing i to avoid the problem:
for (var i = arrayOfObjects.length - 1; i >= 0; i--) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
}
}
Or use filter:
var newArray = arrayOfObjects.filter(function(obj) {
return listToDelete.indexOf(obj.id) === -1;
});
Only native JavaScript please.
As an alternative, more "functional" solution, working on ECMAScript 5, you could use:
var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}]; // all that should remain
arrayOfObjects.reduceRight(function(acc, obj, idx) {
if (listToDelete.indexOf(obj.id) > -1)
arrayOfObjects.splice(idx,1);
}, 0); // initial value set to avoid issues with the first item and
// when the array is empty.
console.log(arrayOfObjects);
[ { id: 'hij', name: 'ge' } ]
According to the definition of 'Array.prototype.reduceRight' in ECMA-262:
reduceRight does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn.
So this is a valid usage of reduceRight.
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
as per your answer will be like this. when you click some particular object send the index in the param for the delete me function. This simple code will work like charm.
function deleteme(i){
if (i > -1) {
arrayOfObjects.splice(i, 1);
}
}
If you like short and self descriptive parameters or if you don't want to use splice and go with a straight forward filter or if you are simply a SQL person like me:
function removeFromArrayOfHash(p_array_of_hash, p_key, p_value_to_remove){
return p_array_of_hash.filter((l_cur_row) => {return l_cur_row[p_key] != p_value_to_remove});
}
And a sample usage:
l_test_arr =
[
{
post_id: 1,
post_content: "Hey I am the first hash with id 1"
},
{
post_id: 2,
post_content: "This is item 2"
},
{
post_id: 1,
post_content: "And I am the second hash with id 1"
},
{
post_id: 3,
post_content: "This is item 3"
},
];
l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 2); // gives both of the post_id 1 hashes and the post_id 3
l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 1); // gives only post_id 3 (since 1 was removed in previous line)
with filter & indexOf
withLodash = _.filter(arrayOfObjects, (obj) => (listToDelete.indexOf(obj.id) === -1));
withoutLodash = arrayOfObjects.filter(obj => listToDelete.indexOf(obj.id) === -1);
with filter & includes
withLodash = _.filter(arrayOfObjects, (obj) => (!listToDelete.includes(obj.id)))
withoutLodash = arrayOfObjects.filter(obj => !listToDelete.includes(obj.id));
You can use filter. This method always returns the element if the condition is true. So if you want to remove by id you must keep all the element that doesn't match with the given id. Here is an example:
arrayOfObjects = arrayOfObjects.filter(obj => obj.id != idToRemove)
Incorrect way
First of all, any answer that suggests to use filter does not actually remove the item. Here is a quick test:
var numbers = [1, 2, 2, 3];
numbers.filter(x => x === 2);
console.log(numbers.length);
In the above, the numbers array will stay intact (nothing will be removed). The filter method returns a new array with all the elements that satisfy the condition x === 2 but the original array is left intact.
Sure you can do this:
var numbers = [1, 2, 2, 3];
numbers = numbers.filter(x => x === 2);
console.log(numbers.length);
But that is simply assigning a new array to numbers.
Correct way to remove items from array
One of the correct ways, there are more than 1, is to do it as following. Please keep in mind, the example here intentionally has duplicated items so the removal of duplicates can be taken into consideration.
var numbers = [1, 2, 2, 3];
// Find all items you wish to remove
// If array has objects, then change condition to x.someProperty === someValue
var numbersToRemove = numbers.filter(x => x === 2);
// Now remove them
numbersToRemove.forEach(x => numbers.splice(numbers.findIndex(n => n === x), 1));
// Now check (this is obviously just to test)
console.log(numbers.length);
console.log(numbers);
Now you will notice length returns 2 indicating only numbers 1 and 3 are remaining in the array.
In your case
To specifically answer your question which is this:
var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
Here is the answer:
listToDelete.forEach(x => arrayOfObjects.splice(arrayOfObjects.findIndex(n => n.id === x), 1));
var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
var result = arrayOfObjects.filter(object => !listToDelete.some(toDelete => toDelete === object.id));
console.log(result);

Categories

Resources