19

Suppose I have an array:

    members = [
        {name: 'Anna', class: 'one'}, 
        {name: 'Bob', class: 'two'},  
        {name: 'Chuck', class: 'two'}];

    removed = members.myRemoveByClass('two');     //something like

    // removed is {name: 'Bob', class: 'two'} 
    // members is [{name: 'Anna', class: 'one'}, {name: 'Chuck', class: 'two'}]

I'm looking for something for myRemoveByClass. ES2015 is fine or using Lodash. The array will have been ordered already. None of the questions I've seen quite match what I'm looking for.

Gazzer
  • 4,524
  • 10
  • 39
  • 49
  • 2
    The posted question does not appear to include [any attempt](https://idownvotedbecau.se/noattempt/) at all to solve the problem. StackOverflow expects you to [try to solve your own problem first](https://meta.stackoverflow.com/questions/261592/how-much-research-effort-is-expected-of-stack-overflow-users), as your attempts help us to better understand what you want. Please edit the question to show what you've tried, so as to illustrate a specific roadblock you're running into a [MCVE]. For more information, please see [ask] and take the [tour]. – CertainPerformance Nov 29 '18 at 08:34
  • 1
    Could you point to where it says we need to show what kind of attempt was made. Should I put the number of hours I spend on the problem or link to all the SO solutions that didn't address the question I asked. Such as https://stackoverflow.com/questions/25726066/equivalent-of-underscore-pluck-in-pure-javascript https://stackoverflow.com/questions/10457264/how-to-find-first-element-of-array-matching-a-boolean-condition-in-javascript https://stackoverflow.com/questions/35136306/what-happened-to-lodash-pluck etc. Putting my efforts here would not clarify the question. – Gazzer Nov 29 '18 at 09:08
  • `Putting my efforts here would not clarify the question.` It would help illustrate that this isn't a no-effort homework dump or write-my-code-for-me-from-scratch question, which are frowned on - see the first two links in my comment above. Searching existing questions for code that does what you want isn't the same thing as trying to write code yourself – CertainPerformance Nov 29 '18 at 10:11
  • 1
    @CertainPerformance `It would help illustrate that this isn't a no-effort homework dump or write-my-code-for-me-from-scratch question` Isn't that the whole point of reputation? `isn't the same thing as trying to write code yourself` Why do you assume that I didn't spend a couple of hours trying to code it myself which I did, and finding my code was not helpful in framing the question? – Gazzer Nov 29 '18 at 11:07

8 Answers8

18

You can use Array.prototype.findIndex():

The findIndex() method returns the index of the first element in the array that satisfies the provided testing function. Otherwise, it returns -1, indicating no element passed the test.

Then splice() the object by that index.

let members = [
        {name: 'Anna', class: 'one'}, 
        {name: 'Bob', class: 'two'},  
        {name: 'Chuck', class: 'two'}];
let idx = members.findIndex(p => p.class=="two");
if(idx >= 0){ //check if item found
  var removed = members.splice(idx, 1);     
  console.log(removed);
  console.log(members);
}
else{ //or not
  console.log('Not found!');
}
Mamun
  • 66,969
  • 9
  • 47
  • 59
  • 4
    This is **dangerously wrong** - if no element is found, `idx` will be -1, and then `members.splice(idx, 1)` will remove the last element of `members`, which is *not* what you want in that case... – Max Feb 07 '22 at 00:08
7

You could create your own Array class:

 class Members extends Array {
   removeByClass(className) {
     for(const [index, member] of this.entries())
        if(member.class === className) 
           return this.splice(index, 1)[0];
   }
}

Use it as

 const members = new Members([ {/*...*/}, {/*...*/} ]);
 members.removeByClass("...");

PS: "class" is a very bad name as it is a reserved keyword

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • I was going to change it, but ESLint didn't seemed to mind `class` there so I left it in! I don't want to edit it now so that the solutions match the question! – Gazzer Nov 29 '18 at 09:19
2

This would also work

removeByClass(array, filterString) {
   const memberToRemove = array.find(element => {
     return element.class === filterString;
   });
   array.splice(array.indexOf(memberToRemove), 1);
 }

 let members = [
  { name: 'Anna', class: 'one' },
  { name: 'Bob', class: 'two' },
  { name: 'Chuck', class: 'two' }];

this.removeByClass(members, 'two');
Teun van der Wijst
  • 939
  • 1
  • 7
  • 21
2

You could find the index of the first occurence and check this index and splice the object from the array.

var members = [{ name: 'Anna', class: 'one' }, { name: 'Bob', class: 'two' }, { name: 'Chuck', class: 'two' }],
    index = members.findIndex(o => o.class === 'two'),
    removed = index !== -1 && members.splice(index, 1);

console.log(removed);
console.log(members);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

You can use Array.prototype.find() combined with Array.prototype.splice()

Code example:

const members = [{ name: 'Anna', class: 'one' }, { name: 'Bob', class: 'two' }, { name: 'Chuck', class: 'two' }]

const removeFirstMatchByClass = (members, className) => {
  const index = members.findIndex(member => member.class === className)
  return index !== -1 ? [...members.slice(0, index), ...members.slice(index + 1)] : [...members]
}

console.log(removeFirstMatchByClass(members, 'two'))
Yosvel Quintero
  • 18,669
  • 5
  • 37
  • 46
1

Simply:

function removeByClass(obj, prop) {
    for (let i = 0; i < obj.length; i++) {
        if (obj[i].class == prop) obj.splice(i, 1);
    }   
}
Oliver
  • 493
  • 2
  • 8
  • 15
1

You could use some method to find the member which needs to be removed and return true to stop the loop.

let members = [
  {name: 'Anna', class: 'one'}, 
  {name: 'Bob', class: 'two'},  
  {name: 'Chuck', class: 'two'}
];

function myRemoveByClass(members, className) {
  let foundMember = null;
  members.some((member, index) => {
    if (member.class == className) {
      members.splice(index, 1);
      foundMember = member;
      return true;
    }
  });
  
  return foundMember;
}

let removed = myRemoveByClass(members, 'two');
console.log(removed);
console.log(members);

As Jonas pointed out here, you should avoid using class as it is a reserved word.

im_tsm
  • 1,965
  • 17
  • 29
1

you can use without and findWhere

var arr = _.without(members , _.findWhere(members , {
 class: "two"
}));
Schüler
  • 512
  • 4
  • 10
  • 25