第 158 题:如何模拟实现 Array.prototype.splice

发布于 2022-05-22 13:41:04 字数 283 浏览 901 评论 15

splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。参考:https://www.wenjiangs.com/wiki/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

空城之時有危險 2022-05-04 13:54:14
Array.prototype.splice = function (start, deleteCount, ...args) {
  // 处理start值
  if (start < 0) {
    if (Math.abs(start) > this.length - 1) {
      start = 0
    } else {
      start += this.length
    }
  }
  // 处理deleteCount值
  deleteCount = typeof deleteCount !== 'undefined' ? deleteCount : this.length
  // 处理args值
  args = args.length ? args : []
  // 处理特殊情况
  if (start > this.length - 1) {
    this.concat(args)
    return []
  }
  /**
   * 思路
   * 先把原数组值取出,原数组清空
   * 先入栈不需要处理的数组前部分元素
   * 然后把需要加入的args
   * 最后入栈数组后部分元素
   * 返回中间删掉的元素组成的数组
   */
  let arr = [...this]
  this.length = 0 // 清空
  // 先入栈前部分元素
  let i = 0
  while (i < start) {
    this.push(arr.shift())
    i++
  }
  // 入栈args
  args.forEach(item => this.push(item))
  // 入栈后部分元素
  arr.forEach((item, index) => {
    if (index >= deleteCount) {
      this.push(item)
      delete arr[index]
    }
  })
  // 返回删除部分
  return arr
}
秋心╮凉 2022-05-04 13:54:14
//@ts-ignore
Array.prototype._splice = function (index: number, count: number, ...args: any[]) {
  const deletes = [];
  let res = [];
  let pushIndex;
  for(let i = 0; i < this.length; i++){
      if(i === index && args.length){
          pushIndex = i;
      }
      if(i >= index && i < (index+count)){
          deletes.push(this[i]);
          continue;
      }
      res.push(this[i]);
  }
  if(pushIndex !== void 0){
      const left = res.slice(0, pushIndex);
      const right = res.slice(pushIndex, res.length);
      res = [...left, ...args, ...right];
  }
  this.length = 0;
  this.push(...res);
  return deletes;
}
长梦不多时 2022-05-04 13:54:14
Array.prototype.spliceMy = function (startIndex, endIndex, ...item) {
    if (startIndex < 0) {
        startIndex = this.length + startIndex
        endIndex = this.length + startIndex + endIndex
    } else {
        endIndex = startIndex + endIndex
    }
    let arrStart = this.slice(0, startIndex)
    let arrEnd = this.slice(endIndex, this.length)
    console.log(arrStart, arrEnd)
    let returnArr = this.slice(startIndex, endIndex)
    let newArr = arrStart.concat(item).concat(arrEnd)
    for (let i = 0; i < newArr.length; i++) {
        this[i] = newArr[i];
    }
    this.length = newArr.length
    return returnArr
}
满身野味 2022-05-04 13:54:14
/**
 * @param {number} idx 开始删除的索引
 * @param {number} deleteCount 需要删除的数目
 * @param {any[]} insertItems 需要插入项
 * @returns {any[]} 被删的数组项的数组
 */
Array.prototype.mySplice = function (idx, deleteCount) {
  var arr = this;
  var length = arr.length;
  var insertItems = [].slice.call(arguments, 2);
  deleteCount =
    typeof deleteCount !== 'undefined' && deleteCount <= length - idx
      ? deleteCount
      : length - idx;
  var res = [];
  while (deleteCount) {
    deleteCount--;
    if (idx in arr) {
      res.push(arr[idx]);
    }
    for (var i = idx; i < arr.length - 1; i++) {
      arr[i] = arr[i + 1];
    }
    arr.length = arr.length - 1;
  }
  for (var j = 0; j < insertItems.length; j++) {
    arr.push(insertItems[j]);
  }
  return res;
};

写了一个TS的,编译了下

孤千羽 2022-05-04 13:54:14

有几点需要注意的:

1、第一个参数,开始下标
2、第二个参数,删除个数
3、从第三个开始往后都是插入的数据

4、操作的都是原数组,也就是改变的是原数组
5、返回一个被删除的数据的新数组

下边这个是我老早之前写的,参考了 chrome 的实现方式

Array.prototype._splice = function () {
  if (arguments.length === 0) return [];
  var arg_len = arguments.length,
    array_len = this.length,
    index = parseInt(arguments[0]) ? parseInt(arguments[0]) : 0,
    num = parseInt(arguments[1])
      ? parseInt(arguments[1]) < 0
        ? 0
        : parseInt(arguments[1])
      : 0;
  // 起始下标
  if (index < 0) {
    index += array_len;
    if (index < 0) {
      index = 0;
    }
  }
  // 删除个数
  if (index + num > array_len) {
    num = array_len - index;
  }
  // 删除
  var new_array = [];
  if (num > 0) {
    for (var i = 0, k = 0; i < array_len; i++) {
      if (i !== index) {
        this[k++] = this[i];
      } else {
        for (var j = 0; j < num; j++) {
          new_array[j] = this[i++];
        }
        i--;
      }
    }
  }
  // 插入数据
  this.length = array_len - num + (arg_len < 2 ? 0 : arg_len - 2);
  if (arg_len === 2) {
    return new_array;
  }
  array_len -= num;
  for (i = this.length - 1; i >= 0; i--) {
    if (i !== index + arg_len - 3) {
      this[i] = this[--array_len];
    } else {
      for (j = arg_len - 1; j > 1; j--, i--) {
        this[i] = arguments[j];
      }
      i++;
    }
  }
  return new_array;
};
做个ˇ局外人 2022-05-04 13:54:14

/***

  • index: 删除的起始下标
  • num:删除个数
  • addlist: 新增的元素
  • returnItem :返回已删除元素
    */
Array.prototype._slice = function(index, num, ...addList) {
    let newArr = []
    let returnItem = []
    while(num > 0) {
        // 起始下标有可能传入负数
        if (index < 0) {
            index += this.length
        }
        // 删除当前项
        returnItem.push(this[index])
        delete this[index]
        index++
        num--
    }
    // 将老数组赋予新数组
    for(const item of arr) {
        if(item) newArr.push(item)
    }
    let length = newArr.length
    for(var i = 0; i< length;i++) {
        this[i] = newArr[i]
    }
    this.length = length
    // 新增元素
    if(addList && addList.length > 0) {
        for(const item of addList) {
            this.push(item)
        }
    }
    return returnItem
}
只等公子 2022-05-04 13:54:14
(function () {

  const del = (arr, index, len) => {
    if (index < 0) {
      index = arr.length - Math.abs(index);
    }
    let i = index + len;
    let result = [];


    let count = len;
    let offset = index;
    while (count--) {
      result.push(arr[offset++]);
    }

    while (i < arr.length) {
      arr[i - len] = arr[i];
      i++;
    }

    arr.length = arr.length - len;
    return result;

  }

  const insert = (arr, index, items) => {
    // arr.length = arr.length + items.length;

    let i = arr.length - 1;

    while (i >= index) {
      arr[i + items.length] = arr[i];
      i--;
    }
    i = 0;
    while (i < items.length) {
      arr[i + index] = items[i];
      i++
    }

  }
  
  Array.prototype._splice = function _splice(index, deleteCount, ...rest) {

    let arr = this;
    let removed = [];
  
    // 只有一个元素
    if (deleteCount === undefined) {
      removed = del(arr, index, arr.length - Math.abs(index));
    } else {
      removed = del(arr, index, deleteCount);
      if (rest.length) {
        insert(arr, index, rest);
      }
    }
  
  
    return removed;
  }
  var myFish = ["angel", "clown", "mandarin", "sturgeon"];
  var removed = myFish._splice(2, 0, "drum");
  console.log(myFish, removed)
  
  // 运算后的 myFish: ["angel", "clown", "drum", "mandarin", "sturgeon"]
  // 被删除的元素: [], 没有元素被删除
  
  var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
  var removed = myFish._splice(2, 0, 'drum', 'guitar');
  console.log(myFish, removed)
  
  // 运算后的 myFish: ["angel", "clown", "drum", "guitar", "mandarin", "sturgeon"]
  // 被删除的元素: [], 没有元素被删除
  
  var myFish = ['angel', 'clown', 'drum', 'mandarin', 'sturgeon'];
  var removed = myFish._splice(3, 1);
  console.log(myFish, removed)
  
  // 运算后的 myFish: ["angel", "clown", "drum", "sturgeon"]
  // 被删除的元素: ["mandarin"]

  var myFish = ['angel', 'clown', 'drum', 'sturgeon'];
  var removed = myFish._splice(2, 1, "trumpet");
  console.log(myFish, removed)

  // 运算后的 myFish: ["angel", "clown", "trumpet", "sturgeon"]
  // 被删除的元素: ["drum"]

  var myFish = ['angel', 'clown', 'trumpet', 'sturgeon'];
  var removed = myFish._splice(0, 2, 'parrot', 'anemone', 'blue');
  console.log(myFish, removed)

  // 运算后的 myFish: ["parrot", "anemone", "blue", "trumpet", "sturgeon"]
  // 被删除的元素: ["angel", "clown"]

  var myFish = ['parrot', 'anemone', 'blue', 'trumpet', 'sturgeon'];
  var removed = myFish._splice(myFish.length - 3, 2);
  console.log(myFish, removed)

  // 运算后的 myFish: ["parrot", "anemone", "sturgeon"]
  // 被删除的元素: ["blue", "trumpet"]

  var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
  var removed = myFish._splice(-2, 1);
  console.log(myFish, removed)

  // 运算后的 myFish: ["angel", "clown", "sturgeon"]
  // 被删除的元素: ["mandarin"]

  var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
  var removed = myFish._splice(2);
  console.log(myFish, removed)

  // 运算后的 myFish: ["angel", "clown"]
  // 被删除的元素: ["mandarin", "sturgeon"]

})()
挥剑断情 2022-05-04 13:54:14
Array.prototype.splice = function(start, delCount, ...items) {
  let arr = this
  let delArr = []
  let end = start
  const len = arr.length
  const startArr = arr.slice(0, start)
  if (delCount && delCount > 0) {
    end += delCount
    delArr = delArr.concat(arr.slice(start, end))
  }
  const endArr = arr.slice(end, len+1)
  const newArr = startArr.concat(items).concat(endArr)
  newArr.forEach((item,index) => {
    this[index] = item
  })
  this.length = newArr.length
  return delArr
}
烟花易冷人易散 2022-05-04 13:54:14
Array.prototype.mySplice = function(start, deleteCount, ...items) {
        const preLen = this.length + items.length
        const rightArr = items.concat(this.slice(start + deleteCount))
        let i = start
        while(rightArr.length) {
          this[i] = rightArr.shift()
          i++
        }
        this.length = preLen - deleteCount
      }
请爱~陌生人 2022-05-04 13:54:14
Array.prototype.mySplice = function(start, deleteCount, ...items) {
        const preLen = this.length + items.length
        const rightArr = items.concat(this.slice(start + deleteCount))
        let i = start
        while(rightArr.length) {
          this[i] = rightArr.shift()
          i++
        }
        this.length = preLen - deleteCount
      }

最短代码数

独享拥抱 2022-05-04 13:54:08

前端的原始API还有没写的吗?

晚风撩人 2022-05-04 13:54:06
// splice
      let arr1 = [1, 3, 5, 7, 9];
      let arr2 = [1, 3, 5, 7, 9];
      /*
          一个参数表示删除后面所有元素
          两个参数表示走a开始删b个元素
          两个以上表示走a开始删b个元素,再这个位置添加元素
        */
      Array.prototype.mySplice = function (index, delCount, ...args) {
        // 判断this
        if (this === null || this === undefined) {
          throw new TypeError(
            "Cannot read property 'map' of null or undefined"
          );
        }
        let O = Object(this),
          len = O.length;
        // 第一个参数,不存在 (返回空数组)
        if (index === undefined) {
          return [];
        }
        index = Number(index);
        // 第一个参数不是数字  (全删除)
        if (isNaN(index)) {
          return delArray(O, 0);
        }
        // index若为负值或者超过length
        index = changeIndex(index, len);

        // 第二个参数没有 (后面的全删除)
        if (delCount === undefined) {
          return delArray(O, index);
        }
        // 第二个参数不是数字 (返回空数组)
        if (isNaN(delCount)) {
          return [];
        } else {
          // 第三个参数存在
          if (Array.isArray(args)) {
            return add(O, index, delCount, args);
          }
          // 不存在
          // 删除数组
          return delArray(O, index, delCount);
        }
      };
      function changeIndex(index, len) {
        // 若为负值
        while (index < 0) {
          index += len;
        }
        // 若为超过len的值
        if (index >= len) {
          index = len;
        }
        return index;
      }
      // 添加元素
      function add(arr, index, count, temp) {
        // 先删除
        let a = delArray(arr, index, count);
        // 添加元素
        for (let i = 0; i < temp.length; i++) {
          // 外层循环添加次数
          for (let j = arr.length; j > index + i; j--) {
            arr[j] = arr[j - 1];
          }
          arr[index + i] = temp[i];
        }
        return a;
      }
      // 删除元素
      function delArray(arr, index, count = arr.length) {
        let temp = [],
          len = arr.length;
        //判断有效的count
        count = len - index >= count ? count : len - index;
        for (let i = 0; i < count; i++) {
          let item = arr[index + i];
          temp.push(item);
        }
        while (count) {
          count--;
          for (let j = index; j < arr.length - 1; j++) {
            arr[j] = arr[j + 1];
          }
          let len_ = arr.length - 1;
          delete arr[len_];
          arr.length = len_;
        }
        return temp;
      }
      let res1 = arr1.mySplice(1, 1, 111, 222, 333);
      let res2 = arr2.splice(1, 1, 111, 222, 333);
      console.log(res1, arr1, res2, arr2);
像极了他 2022-05-04 13:53:21
Array.prototype.splice = function(start, deleteCount, ...items) {
    let deletedItems = [];

    if (Object.is(arguments.length, 0)) return deletedItems;

    const length = this.length;

    let actualStart = +start || 0;
    actualStart =  actualStart >= 0 ? Math.min(actualStart, length) : Math.max(length + actualStart, 0); // 防止 start 越界

    let actualDeleteCount;
    if (Object.is(arguments.length, 1)) {
        actualDeleteCount = length - actualStart; // 未传 deleteCount 时默认删除 start 右侧所有元素
    } else {
        actualDeleteCount = Math.min(Math.max(+deleteCount, 0), length - actualStart); // 防止 deleteCount 大于 start 右侧所有元素长度
    }

    deletedItems = this.slice(actualStart, actualStart + actualDeleteCount); // 待删除元素

    const resetItems = this.slice(actualStart + actualDeleteCount); // 右侧剩余元素
    [...items, ...resetItems].forEach(item => this[actualStart++]=item);  // 将待添加元素与右侧剩余元素添加至原数组中
    
    this.length = actualStart;

    return deletedItems;
}
仄言 2022-05-04 13:53:21

Array.prototype.mySplice = function (start, count, ...args) {
const len = this.length
let _start = start
let res = []
let thisArr = []
function setThis(that, arr) {
arr.forEach((v, index) =>that[index] = v)
that.length = arr.length
}
if (start < 0) {
_start = len + start
_start = _start < 0 ? 0 : _start
}
if (start > len) {
_start = len
}
if (count === undefined) {
res = this.slice(_start)
setThis(this, this.slice(0, _start))
return res
}
res = this.slice(_start, _start + count)
const left = this.slice(0, _start)
const right = this.slice(_start + count)
setThis(this, left.concat(args, right))
return res
}

骑趴! 2022-05-04 12:23:01
Array.prototype._splice = function (start, deleteCount, ...addList) {
        if (start < 0) {
            if (Math.abs(start) > this.length) {
                start = 0
            } else {
                start += this.length
            }
        }

        if (typeof deleteCount === 'undefined') {
            deleteCount = this.length - start
        }

        const removeList =  this.slice(start, start + deleteCount)

        const right = this.slice(start + deleteCount)

        let addIndex = start
        addList.concat(right).forEach(item => {
            this[addIndex] = item
            addIndex++
        })
        this.length = addIndex

        return removeList
    }
~没有更多了~

关于作者

乱了心跳

暂无简介

0 文章
0 评论
25 人气
更多

推荐作者

已经忘了多久

文章 0 评论 0

15867725375

文章 0 评论 0

LonelySnow

文章 0 评论 0

走过海棠暮

文章 0 评论 0

轻许诺言

文章 0 评论 0

信馬由缰

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文