在Javascript中搜索数组时如何修复输出“未定义”

时间:2019-08-23 00:56:04

标签: javascript arrays search

我试图制作一个JavaScript代码,在对象数组内搜索文本,然后删除整个索引(包括text属性的索引),但是代码失败并始终返回“ undefined”,因此我想获取一些帮助。

const todos = [{
    text: 'wake up',
    completed: true
}, {
    text: 'get some food',
    completed: false
}, {
    text: 'play csgo',
    completed: false
}, {
    text: 'play minecraft',
    completed: true
}, {
    text: 'learn javascript',
    completed: false
}]



let todo = function (todo, todoText) {
    return todo.find(function (text, index) {
        if (todo.text.toLowerCase() === todoText.toLowerCase()) {
            todo.splice(index, 1);
        }
    })
}

let deleteTodo = todo(todos, 'wake up');
console.log(deleteTodo);

我期望得到这样的输出:

[{
    text: 'get some food',
    completed: false
}, {
    text: 'play csgo',
    completed: false
}, {
    text: 'play minecraft',
    completed: true
}, {
    text: 'learn javascript',
    completed: false
}]

但是输出实际上是'undefined'

5 个答案:

答案 0 :(得分:2)

.find()要求函数在条件匹配时返回真实值。您的函数不会返回任何内容,它只会将元素拼接起来,因此find()永远不会返回匹配的元素。

您只需在拼接元素后添加return true;

let todo = function(todo, todoText) {
  todoText = todoText.toLowerCase();
  return todo.find(function(text, index) {
    if (text.text.toLowerCase() === todoText) {
      todo.splice(index, 1);
      return true;
    } else {
      return false;
    }
  })
}

const todos = [{
    text: 'wake up',
    completed: true
}, {
    text: 'get some food',
    completed: false
}, {
    text: 'play csgo',
    completed: false
}, {
    text: 'play minecraft',
    completed: true
}, {
    text: 'learn javascript',
    completed: false
}];

let deleteTodo = todo(todos, 'wake up');
console.log("Object that was removed:", deleteTodo);
console.log("Array that remains:", todos);

我以前写过,您不应在搜索时修改数组。但是Array.prototype.find的规范允许这样做,因为它在调用test函数之前从数组中提取了元素。由于仅在找到匹配项时才修改数组,因此不会影响其余的迭代。

答案 1 :(得分:1)

出于不变性的考虑,我会过滤该数组以产生一个没有匹配记录的新数组,即

return todo.filter(({text}) => todoText.localeCompare(text, undefined, {
  sensitivity: 'base'
}))
如果字符串匹配(忽略大小写)或0 / -1,则

String.prototype.localeCompare()将返回+1值( falsy ) > truthy )(如果没有)。可以用来让Array.prototype.filter()知道是否在最终数组中包括该条目。

const todos = [{
    text: 'wake up',
    completed: true
}, {
    text: 'get some food',
    completed: false
}, {
    text: 'play csgo',
    completed: false
}, {
    text: 'play minecraft',
    completed: true
}, {
    text: 'learn javascript',
    completed: false
}]

let todo = (todos, todoText) =>
  todos.filter(({ text }) => text.localeCompare(todoText, undefined, {
    sensitivity: 'base'
  }))

let deleteTodo = todo(todos, 'WAKE UP');
console.log(deleteTodo);

答案 2 :(得分:1)

我认为有一个更好的函数可以解决它:过滤器

let res = todos.filter( elem => elem.text.toLowerCase() !== 'wake up');

如果您希望它成为一个函数,它将类似于:

let result = (todos, todoText) => {
  return todos.filter( elem => elem.text.toLowerCase() !== todoText.toLowerCase() );
}
console.log(result(todos, 'wake up'));

答案 3 :(得分:0)

不是因为向后兼容,所以我会使用.find,但是如果您坚持:

const todos = [{
    text: 'wake up',
    completed: true
}, {
    text: 'get some food',
    completed: false
}, {
    text: 'play csgo',
    completed: false
}, {
    text: 'play minecraft',
    completed: true
}, {
    text: 'learn javascript',
    completed: false
}];
let deleteTodo = function(todos, todoText){
  var e = todos.find(function(text){
    if(text.text.toLowerCase() === todoText.toLowerCase()){
      return true;
    }
  });
  return todos.splice(todos.indexOf(e), 1);
}
console.log(deleteTodo(todos, 'wake up')); // deleted
console.log(todos); // altered array

这是向后兼容的版本:

var todos = [{
    text: 'wake up',
    completed: true
}, {
    text: 'get some food',
    completed: false
}, {
    text: 'play csgo',
    completed: false
}, {
    text: 'play minecraft',
    completed: true
}, {
    text: 'learn javascript',
    completed: false
}];
function TodoWorker(todos){
  this.todos = todos;
  this.remove = function(text){
    for(var i=0,a=this.todos,l=a.length; i<l; i++){
      if(a[i].text === text){
        return a.splice(i, 1);
      }
    }
  }
}
var tw = new TodoWorker(todos);
console.log(tw.remove('play csgo')); // deleted element
console.log(tw.todos); // altered array
console.log(tw.remove('play minecraft')); // deleted element
console.log(tw.todos); // altered array - what you should be doing

您可以看到第二种方法既向后兼容,又允许您在todos方法中省略.remove参数。

答案 4 :(得分:0)

我认为您的代码可以稍作修改即可工作:

const todos = [{
    text: 'wake up',
    completed: true
}, {
    text: 'get some food',
    completed: false
}, {
    text: 'play csgo',
    completed: false
}, {
    text: 'play minecraft',
    completed: true
}, {
    text: 'learn javascript',
    completed: false
}]



 function todo(todo, todoText) {
     let result = [];
     for (let index = 0; index < todo.length; index++) {
      
        if (todoText.toLowerCase() === todo[index].text.toString().toLocaleLowerCase()) {
        console.log("the deleted todo :",todo[index].text.toString().toLocaleLowerCase())
    }else{
            result.push(todo[index])
        }

     }
     return result;
}

let deleteTodo = todo(todos, 'wake up');
console.log(deleteTodo);

我使用另一个变量存储结果,对循环和函数进行了一些更改。 希望对您有帮助