从对象的键数组中删除单一元素

4

我有一个对象,该对象有多个键,每个键都有一个存储多个元素的数组。我想能够从键的数组中删除指定的元素。

我尝试使用delete关键字以及filter方法,但我一直不成功。我是JS的新手,所以非常感谢任何帮助。此外,我想仅使用JavaScript完成此操作,不使用库。

这是我创建对象的代码:

function add(task, weekdayDue) {
   let capitalWeekday = weekdayDue.charAt(0).toUpperCase() + 
      weekdayDue.slice(1);
   if (toDoList[capitalWeekday] === undefined) {
      let subArr = [];
      toDoList[capitalWeekday] = subArr.concat(task); 
   } else {
      toDoList[capitalWeekday].push(task);
     }
   }

这是我现在拥有的代码。显然它并没有产生正确的结果:

 function remove(task, weekdayDue) {
    let capitalWeekday = weekdayDue.charAt(0).toUpperCase() + 
    weekdayDue.slice(1);
    delete toDoList.capitalWeekday[task] 
    //the below code is working; i want to send this to another 
     array
    if (archivedList[capitalWeekday] === undefined) {
       let subArr = [];
       archivedList[capitalWeekday] = subArr.concat(task);
     } else {
       archivedList[capitalWeekday].push(task);
     }
   };


 add('laundry', 'monday');
 add('wash car', 'monday');
 add ('vacuum', 'tuesday');
 add('run errands', 'wednesday');
 add('grocery shopping', 'wednesday');

 // the output is:  { Monday: [ 'laundry', 'wash car' ],
 Tuesday: [ 'vacuum' ],
 Wednesday: [ 'run errands', 'grocery shopping' ] }

然后假设我想从星期一中删除“洗车”,我尝试了以下操作:
 remove('wash car', 'monday');
 console.log(toDoList)

// The output is an empty object {}

如果您添加一个结构示例以及在调用 remove() 后期望的输出,就可以更好地理解此内容。 - Shidersz
“result”和“output”是什么意思 - 你在谈论哪个变量,因为你的函数没有返回或显示任何内容。 - James
请问您能否添加一些示例输入和输出? - Jack Bashford
我不知道你对象的确切结构,但是如何为每个键找到其数组,并对该数组中的每个元素检查它是否是要删除的元素呢?如果是,就使用splice方法进行删除 - David
是的,对此很抱歉。 - S.W
3个回答

2
我个人认为你的代码需要进行一些重构,但我已经解决了一些问题。

首先,对于你的情况,你不应该使用delete,因为它会将数组中第n个位置的项重置为默认值undefined。通常,对于这种操作,由于你处理的是字符串,你应该查找数组中你的项的第一个出现位置,获取其索引,并使用splice (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) 来实际从数组中删除该项。

这样,你就可以得到一个没有无效项的干净数组。

以下是可工作的代码(带有上述修复),它可以完成你所要求的功能。另外,我建议你避免为此类目的使用字符串,而是应该使用具有唯一id的对象,这样在数组和对象之间跟踪它们会更容易。

此外,还有一些你没有考虑到的情况,例如我可以通过提供无效的task来调用remove,因此你可能需要稍微修改下面的代码以处理taskIndex为-1(表示没有找到该索引的项)的情况。

var toDoList = {}, archivedList = {};

function add(task, weekdayDue) {
 let capitalWeekday = weekdayDue.charAt(0).toUpperCase() + weekdayDue.slice(1);
 if (toDoList[capitalWeekday] === undefined) {
    let subArr = [];
    toDoList[capitalWeekday] = subArr.concat(task); 
 } else {
  toDoList[capitalWeekday].push(task);
 }
}

function remove(task, weekdayDue) {
  let capitalWeekday = weekdayDue.charAt(0).toUpperCase() + weekdayDue.slice(1);
  let taskIndex = toDoList[capitalWeekday].indexOf(task);
  toDoList[capitalWeekday].splice(taskIndex, 1);
  //delete toDoList[capitalWeekday][taskIndex];
  if (archivedList[capitalWeekday] === undefined) {
   let subArr = [];
   archivedList[capitalWeekday] = subArr.concat(task);
 } else {
   archivedList[capitalWeekday].push(task);
 }
};

add('test', 'monday');
add('wash car', 'monday');
remove('wash car', 'monday');

console.log(toDoList);
console.log(archivedList);


你提出了一些有价值的观点,但是使用 Array.filter 比查找索引并进行 splice 更容易和更清晰。而且你可以达到相同的结果 :) - Bruno Monteiro
过滤器性能不佳且会创建一个新数组。由于您只需要删除一个项目,因此过滤器不是最好的解决方案,至少对我来说是这样的 ;) - briosheje

1
function remove(task, weekdayDue) {
  let capitalWeekday = weekdayDue.charAt(0).toUpperCase() + 
  weekdayDue.slice(1);

  // Assign new array with all elements but task
  toDoList[capitalWeekday] = toDoList[capitalWeekday].filter(i => i !== task)
};

add('foo'...
add('bar'...

"{
  "Baz": [
    "Foo",
    "Bar"
  ]
}"

remove('foo'...

"{
  "Baz": [
    "Bar"
  ]
}"

1
你走在正确的道路上。也许你在使用filter时遇到麻烦是因为filter会返回一个新的数组而不是修改当前的数组。你可以更新你的remove函数,并替换这一行:

delete toDoList.capitalWeekday[task]

用以下内容:

toDoList.capitalWeekday = toDoList.capitalWeekday.filter((item) => {return item !== task});


太好了,谢谢!之前我尝试使用筛选器时,我认为我没有正确地筛选出元素,但这非常有帮助。感激不尽! - S.W
不客气,很高兴知道它对你有帮助!如果您认为这是正确的答案,请接受它以帮助我 :) - Bruno Monteiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接