【问题标题】:Why is my removeNumbersLessThan function not working properly?为什么我的 removeNumbersLessThan 功能无法正常工作?
【发布时间】:2019-08-01 19:48:29
【问题描述】:

我必须编写一个函数,该函数接受一个数字和一个对象,然后输入并返回一个已删除所有小于指定数字的数字的对象。

我在问题集中的前一个问题上完成了一个类似的功能,它执行相反的操作,removeNumbersGreaterThan。我所做的只是复制与上一个问题相同的代码,并将大于符号替换为小于符号,但由于某种原因,它并非在所有情况下都有效。

我已经尝试将其更改为小于或等于

function removeNumbersLessThan(num, obj) {
  var i = 0;
  while (i < Object.keys(obj).length) {
    if (Object.values(obj)[i] < num) {
      delete obj[Object.keys(obj)[i]]
    }
    i++;
  }
  return obj;
}

//test
var obj = {
  a: 4,
  b: 6,
  c: 5,
  d: 3
}

removeNumbersLessThan(7, obj)
console.log(obj)

//returns b:6 d:3 -- should return empty object

我注意到它无论如何都会返回第二个值。即使它小于 num 值。 在向我的对象添加更多元素后,我注意到它跳过了对象中的所有其他元素。 我还发现之前的相反功能起作用的原因是因为测试跳过了这些情况。在进一步调查后,它也有同样的问题。

【问题讨论】:

  • 注意,最好使用for ... in 来遍历对象的键

标签: javascript object


【解决方案1】:

当您的循环从obj 中删除一个值时,该键将不再从Object.keys 返回。
但是您仍然会增加 i 计数器,因此每次从 obj 中删除一个键时,您都会“跳过”一个键。

您可以通过只获取一次对象键并在删除属性之前存储它们来解决此问题:

function removeNumbersLessThan(num, obj) {
  let keys = Object.keys(obj);
  for (let key of keys) {
    if (obj[key] < num) {
      delete obj[key];
    }
  }
  return obj;
}

//test
var obj = {
  a: 4,
  b: 6,
  c: 5,
  d: 3
};
removeNumbersLessThan(7, obj);
console.log(obj);

如果您不想改变对象,则可以复制所有大于或等于新对象的属性:

function removeNumbersLessThan(num, obj) {
  let result = {};
  for(let [key, value] of Object.entries(obj))
    if(value >= num)
      result[key] = value;
  return result;
  }

let obj = {
  a: 4,
  b: 6,
  c: 5,
  d: 3,
  e: 8
};
console.log(removeNumbersLessThan(7, obj));

【讨论】:

    【解决方案2】:

    您对对象进行变异,并在每个带有已删除属性的循环中获得一个新的长度,在这个花瓶中索引是前一个。

    此解决方案不可取,因为每次迭代都会获得新的键和值。

    function removeNumbersLessThan(num, obj) {
        var i = 0;
        while (i < Object.keys(obj).length) {
            if (Object.values(obj)[i] < num) {
                delete obj[Object.keys(obj)[i]];
            } else {
                i++; // increment only if not deleted
            }
        }
        return obj;
    }
    
    var obj = { a: 4, b: 6, c: 5, d: 3 };
    
    removeNumbersLessThan(7, obj);
    console.log(obj); // {}

    相反,您可以使用for ... in statement 获取密钥。然后用这个键检查。

    function removeNumbersLessThan(num, object) {
        for (let key in object) {
            if (object[key] < num) {
                delete object[key];
            }
        }
        return object;
    }
    
    var obj = { a: 4, b: 6, c: 5, d: 3 };
    
    removeNumbersLessThan(7, obj);
    
    console.log(obj); // {}

    【讨论】:

    • 虽然正确,但这并没有解决 OP 问题的“为什么”部分 - 迭代期间底层列表的突变 :)
    【解决方案3】:

    首先,请注意,当您删除对象上的key(即更改对象)时,Object.keys() 返回的数组的length 属性将在每次迭代中减少,同时您递增i 变量在每次迭代中,所以最后你不会遍历对象的所有属性。

    在这种特殊情况下,我更喜欢使用 for ... in 来遍历对象键而不是 while 循环,使用以下逻辑:

    function removeNumbersLessThan(num, obj)
    {
        for (const key in obj)    
        {
            if (obj[key] < num)
                delete obj[key];
        }
    
        return obj;
    }
    
    console.log(removeNumbersLessThan(7, {a:4, b:6, c:5, d:3}));
    console.log(removeNumbersLessThan(5, {a:4, b:6, c:5, d:3}));
    .as-console {background-color:black !important; color:lime;}
    .as-console-wrapper {max-height:100% !important; top:0;}

    【讨论】:

      【解决方案4】:

      使用reduce版本...

      function removeNumbersLessThan(num, obj) {
        return Object.keys(obj).reduce((accum, next) => {       
              if (obj[next] >= num)
                return {...accum, [next]: obj[next]};
              else
                return accum;
        },{});
      }
      
            //test
            var obj = {
              a:4,
              b:6,
              c:5,
              d:3
            } 
      
      let x = removeNumbersLessThan(7,obj);
      
      console.log(x);
      

      【讨论】:

        猜你喜欢
        • 2021-01-15
        • 1970-01-01
        • 1970-01-01
        • 2022-07-29
        • 2020-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-16
        相关资源
        最近更新 更多