【问题标题】:Returning an array without a removed element? Using splice() without changing the array?返回一个没有删除元素的数组?使用 splice() 而不更改数组?
【发布时间】:2011-07-26 03:27:30
【问题描述】:

我想做这样的事情:

var myArray = ["one","two","three"];
document.write(myArray.splice(1,1));
document.write(myArray);

所以它首先显示“一,三”,然后是“一,二,三”。我知道 splice() 返回删除的元素并更改数组,但是是否有函数返回删除元素的新数组?我试过了:

window.mysplice = function(arr,index,howmany){
    arr.splice(index,howmany);
    return arr;   
};

如果我尝试:

var myArray = ["one","two","three"];
document.write(mySplice(myArray,1,1));
document.write(myArray);

它仍然会改变 myArray。

【问题讨论】:

    标签: javascript arrays


    【解决方案1】:

    你想要slice:

    返回数组的一部分的一级深拷贝。

    如果你

    a = ['one', 'two', 'three' ];
    b = a.slice(1, 3);
    

    那么a 仍将是['one', 'two', 'three']b 将是['two', 'three']。不过请注意 slice 的第二个参数,它比您要切出的最后一个索引多一个:

    结束提取的从零开始的索引。 slice 最多提取但不包括 end

    【讨论】:

    • 这是如何获得投票的?它没有为 OP 问题提供解决方案...... OP 想要调用一个函数,该函数返回没有一个元素的数组而不修改原始数组。您的建议是调用一个函数,该函数将返回数组的一个元素而不修改原始元素。不合适。
    • 这是错误的,a 将是 ['one']。谁赞成这个?
    • @MedunoyeLaxusGbenga 您正在考虑 splice,它会更改原始数组,从而 slice 实际上会返回一个副本(尽管理所当然,但 slice 和 splice 并不直观地齐头并进,而且 imo 它们可能是更好的设计)。
    • 是的,@JimJam 我把这部分误认为是接受了,我的错。
    【解决方案2】:

    正如下面的答案所建议的,这是一个代码快照

    var myArray = ["one", "two", "three"];
    var cloneArray = myArray.slice();
    
    myArray.splice(1, 1);
    
    console.log(myArray);
    console.log(cloneArray);

    【讨论】:

    • 为什么内存使用量无故翻倍?
    • 谢谢。是否在这里创建了指针?我不明白为什么它会改变原始数组....
    • 作者实际上想要删除元素的数组[“one”,“three”],而不是删除元素(“two”)。
    • @Neverever myArray 删除了元素的数组。 cloneArray 是一个新数组,myArray 的原始内容完好无损。
    【解决方案3】:

    使用这个:

    function spliceNoMutate(myArray,indexToRemove) {
        return myArray.slice(0,indexToRemove).concat(myArray.slice(indexToRemove+1));
    }
    

    【讨论】:

      【解决方案4】:

      我知道这个问题很老,但这种方法可能会派上用场。

      var myArray = ["one","two","three"];
      document.write(myArray.filter(function(v, index) { return index !== 1 })
      

      var myArray = ["one","two","three"];
      document.write(myArray.filter(function(v, index) { return v !== "two" })
      

      这使用Array.filter() 函数并针对索引为1 或值为“二”进行测试。


      现在,我不能保证这些解决方案的性能(因为它检查数组中的每个项目,Nguyen 的answer 可能更有效),但如果你想做更复杂的事情,它会更灵活,而且肯定更容易理解。

      【讨论】:

        【解决方案5】:

        你可以使用 ES6 的传播特性:

        let myArray = ['one','two','three'];
        let mySplicedArray = [...myArray];
        mySplicedArray.splice(1,1); 
        
        console.log(myArray); /// ['one', 'two', 'three']
        console.log(mySplicedArray); /// ['one', 'three']
        

        【讨论】:

        • mySplicedArray 将包含从myArray 的副本中删除的元素(['two']),而不是原始数组减去删除的元素(['one','three']) .作者想要后者。我认为作者会想要这个:let mySplicedArray = [...myArray]; mySplicedArray.splice(1,1); console.log(myArray); 导致 ['one','three']
        【解决方案6】:

        https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

        const oneTwoThree = ['one', 'two', 'three'] // original array
        
        // `filter()` (like most array functions) iterates over every item in the array.
        // Whatever returns true here is copied to a new array (the `oneThree` variable).
        // `item !== 'two'` returns true for everything except 'two'
        const oneThree = oneTwoThree.filter(item => item !== 'two')
        
        console.log(oneTwoThree) // ['one', 'two', 'three'] — the original, unscathed, array
        console.log(oneThree) // ['one', 'three'] — a copy of the original, sans the value you wanted to remove
        

        您希望这样做,以便拥有一个非变异数组。

        我认为性能不如 slice + concat 之类的东西好,但是如果它成为一个问题,请担心(除非你处理数以万计的问题,否则它可能不会数组中的元素)。在那之前,filter 真的很干净。

        另请注意,这将从数组中删除元素 two 的所有实例,因此请确保您的数组中没有可能无意中被这种方法吞噬的重复项。

        【讨论】:

        • 如果您的阵列上有重复的项目,但您只想删除一个怎么办?
        • 为什么要用_作为参数名?通常这是在你不打算使用参数时,如果你打算使用它,你会给它一个名字
        • 这些都是好点。根据我的经验,大多数情况下,当您想要执行 OP 建议的操作时,您不会处理重复项(例如国家/地区列表或其他内容),但您是对的,请注意这一点。我还将 lambda var 从 _ 更新为 item 以反映正确的约定。对不起!
        【解决方案7】:

        我认为从数组中拼接一个元素而不发生变异和不复制自身的最佳方法是使用过滤器:

        arr = ["one", "two", "three"]
        elToRemove = "two"
        filteredArr = arr.filter( n => n != elToRemove)
        
        console.log(arr) // ["one", "two", "three"]
        console.log(filteredArr) // ["one", "three"]
        

        【讨论】:

          【解决方案8】:

          如果你有想要移除的元素的索引,你可以使用 slice() 和 spread 语法:

          let fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
          let removeIndex = 2;
          let iHateLemons = [...fruits.slice(0, removeIndex), ...fruits.slice(removeIndex+1)]
          
          // your new array
          // console.log(iHateLemons) --> ["Banana", "Orange", "Apple", "Mango"]
          // original array still intact
          // console.log(fruits) --> ["Banana", "Orange", "Lemon", "Apple", "Mango"]
          

          【讨论】:

            【解决方案9】:

            而不是这个:

            document.write(myArray.splice(1,1));
            

            为什么不直接使用:

            document.write(myArray[1]);
            

            splice() 根据定义修改数组。如需副本,请参阅slice()

            【讨论】:

              【解决方案10】:

              为什么不直接引用索引?

              var myArray = ["one","two","three"];
              document.write(myArray[1] + '<br />');
              document.write(myArray);
              

              示例:http://jsfiddle.net/AlienWebguy/dHTUj/

              【讨论】:

                【解决方案11】:

                我认为最简洁的方法是创建一个简单的函数,如果需要全局访问,将函数绑定到 Array 原型。

                提供给该问题的大多数答案都是错误的。人们会混淆在不修改其内容的情况下返回一个数组的一个元素,但 OP 需要的是返回一个没有一个元素的数组的克隆。

                这是我的解决方案:

                let arr = ['one', 'two', 'three'];
                
                /* functional */
                window.cloneSlice = (arr, start, end) => {
                  const _arr = arr.slice();
                  _arr.splice(start, end);
                  return _arr;
                }
                // usage
                console.log(cloneSlice(arr, 1, 1)); // one, three
                console.log(arr); // one, two, three
                
                /* prototyped */
                Array.prototype.cloneSlice = function (start, end) { return cloneSlice(this, start, end) }
                // usage
                console.log(arr.cloneSlice(1, 1)); // one, three
                console.log(arr); // one, two, three

                【讨论】:

                  【解决方案12】:
                  const getSubArr = (arr, start, end) => {
                      return end > start
                          ? arr.filter((_, i) => i >= start && i < end)
                          : arr.filter((_, i) => i >= start || i < end);
                  };
                  

                  此函数返回一个数组,它是原始数组的序列。它的优点是它可以用来获取一个没有位于原始数组中间的序列的子数组。

                  const chars = ["a", "b", "c", "d", "e", "f"];
                  console.log(getArrInRange(chars, 2, 4));
                  console.log(getArrInRange(chars, 4, 2));
                  

                  【讨论】:

                    【解决方案13】:
                    document.write(myArray.filter(e => e !== "two"));
                    document.write(myArray);
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-07-30
                      • 2021-09-23
                      • 1970-01-01
                      • 2021-04-19
                      • 2016-10-31
                      • 1970-01-01
                      相关资源
                      最近更新 更多