Daily-Interview-Question icon indicating copy to clipboard operation
Daily-Interview-Question copied to clipboard

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

Open yygmind opened this issue 4 years ago • 45 comments

yygmind avatar May 19 '20 01:05 yygmind

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
    }

kt3721 avatar May 19 '20 02:05 kt3721

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;
}

hexuan-aurora avatar May 19 '20 06:05 hexuan-aurora

Array.prototype._splice = function(start, deleteCount, ...items) {
  if (start > 0) {
    if (start > this.length - 1) {
      start = this.length - 1;
    }
  } else  {
    if (Math.abs(start) > this.length - 1) {
      start = 0;
    } else {
      start = this.length - 1 + start;
    }
  }

  const newArr = [];
  const removed = [];

  deleteCount = isNaN(Number(deleteCount)) ? 0 : Number(deleteCount);

  for (let i = 0; i < this.length; i++) {
    if (i < start || i > start + deleteCount - 1) {
      newArr.push(this[i]);
    } else {
      removed.push(this[i])
    }
    if (i === start + deleteCount - 1) {
      newArr.push(...items)
    }
  }

  for (let i = 0; i < newArr.length; i++) {
    this[i] = newArr[i];
  }

  this.length = newArr.length;

  return removed;
}

zitup avatar May 19 '20 07:05 zitup

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 }

yaoqifa avatar May 19 '20 12:05 yaoqifa

// 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);

weiweixuan avatar May 21 '20 07:05 weiweixuan

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

wulichenyang avatar May 22 '20 12:05 wulichenyang

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
}

listentolife avatar May 24 '20 13:05 listentolife

//@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;
}

1eeing avatar May 26 '20 03:05 1eeing

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
}

sheepshine avatar May 26 '20 10:05 sheepshine

/**
 * @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的,编译了下

fengqinglingyu avatar Jun 01 '20 07:06 fengqinglingyu

有几点需要注意的:

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;
};

ZangYuSong avatar Jun 08 '20 03:06 ZangYuSong

/***

  • 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
}

czz362100 avatar Jun 09 '20 07:06 czz362100

(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"]

})()

GuoYiJi avatar Jun 12 '20 07:06 GuoYiJi

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
}

lvwxx avatar Jun 15 '20 09:06 lvwxx

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
      }

NathanHan1 avatar Jun 22 '20 07:06 NathanHan1

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
      }

最短代码数😝

NathanHan1 avatar Jun 22 '20 07:06 NathanHan1

各位大佬指点一下


Array.prototype.splice = function (index, howmany, ...items) {
    items = items || []

    var arr = this
    var len = arr.length
    var deleteItems = []
    if (howmany == items.length) {
        for (var i = index; i < index + howmany; i++) {
            deleteItems.push(arr[i])
            arr[i] = items[i - index]
        }
    } else if (howmany > items.length) {
        var i = index
        var temp = howmany
        while (howmany) {
            deleteItems.push(arr[i])
            arr[i] = items[i - index]
            i++
            howmany--
        }
        for (var i = index + items.length; i < len; i++) {
            arr[i] = arr[i + temp - items.length]
        }
        arr.length = len - (temp - items.length)

    } else if (howmany < items.length) {
        var step = items.length - howmany
        var i = len + step - 1
        while (i >= index) {

            if (i < items.length + index) {
                arr[i] = items[i - index]
            } else {
                arr[i] = arr[i - step]
            }
            i--
        }


    }
    return deleteItems
}

var arr = [0, 1, 2, 3, 4, 5, 6]
arr.splice(3, 3, ...[7, 8, 9])
console.log(arr)

yangchaojie456 avatar Aug 31 '20 12:08 yangchaojie456

index, delCount, ...args

大佬,你这个好像有点问题啊,这块就有点问题,第二个参数没有,应该从第一个参数开始往后删除,不应该直接全删除吧

// 第二个参数没有 (后面的全删除)
if (delCount === undefined) {
    return delArray(O, index);
}

xueshuai avatar Sep 01 '20 01:09 xueshuai

Array.prototype._splice = function (index, deleteCount, ...items) {
        if (index > this.length || index < 0) {
            console.error("start index should between 0 and self length");
            return;
        }
        var deleteNum = deleteCount >= 0 ? deleteCount : 0;
        var preList = [], suffixList = [], replaceList = [];
        for (let i = 0; i < this.length; i++) {
            if (i < index) {
                preList.push(this[i]);
            } else {
                suffixList.push(this[i]);
            }
        }

        while (deleteNum--) {
            replaceList.push(suffixList[0]);
            suffixList.shift();
            if (!deleteNum) break
        }

        preList = preList.concat(items).concat(suffixList);
        preList.forEach((v, i) => {
            this[i] = v
        });

        return replaceList;
    };

zhangfytech avatar Sep 05 '20 07:09 zhangfytech

/**
 * Array.prototype.splice polyfill
 * 时间复杂度: o(1n) 一次遍历
 * 空间复杂度: o(1n) 原地算法
 */
Array.prototype.splice = function(start, deleteCount, ...items) {
  if (typeof start !== 'number' || isNaN(start)) {
    throw new TypeError('start must be a number');
  }
  if (start < 0) {
    start = this.length - start;
  }

  if (deleteCount !== undefined &&
    (typeof deleteCount !== 'number' || isNaN(deleteCount) )
  ) {
    throw new TypeError('deleteCount must be a number');
  }
  if (deleteCount === undefined || deleteCount > this.length - start ) {
    deleteCount = this.length - start;
  }

  const res = [];
  // 计算移动方向, 不同的移动方向操作不同
  // 左移: 从左往右遍历
  // 右移: 从右往左移动
  let moveVector = items.length - deleteCount,
    // 待插入的元素个数
    pendingIntert = items.length;
    if (moveVector <= 0) {
      for (let i = start; i < this.length; i++) {
        // 记录删除的元素
        if (i - start < deleteCount) {
          res.push(this[i]);
        }
        if (i < this.length + moveVector) {
          // 如果有未插入的元素, 先插入
          if (pendingIntert > 0) {
            this[i] = items[items.length - pendingIntert--];
          } else {
            // 如果没有未插入元素, 左移
            this[i] = this[i - moveVector];
          }
        }
      }
      // 缩减数组长度
      this.length = this.length + moveVector;
    } else {
      for (let i = this.length + moveVector - 1; i >= start; i--) {
        // 记录删除的元素
        if (i - start < deleteCount) {
          res.unshift(this[i]);
        }
        if (i < start + items.length) {
          // 开始插入元素
          this[i] = items[--pendingIntert];
        } else {
          // 右移
          this[i] = this[i - moveVector];
        }
      }
    }
  return res;
}

const testArr = [1, 2, 3];
console.log('res', testArr.splice(0, 1, 4, 5, 6, 7));
console.log(testArr);

caoyi5225 avatar Sep 07 '20 07:09 caoyi5225

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
      }

最短代码数😝

没有看到返回值

slogeor avatar Sep 16 '20 12:09 slogeor

Array.prototype.splice2 = function(start, delCount, ...args) {
  let firstPart = []
  let secondPart = []
  let res = []
  start = start > 0 ? start : (this.length + start)
  delCount = delCount || this.length - start
  for (let i = 0; i < this.length; i++) {
    if (i < start) {
      firstPart.push(this[i])
    } else {
      secondPart.push(this[i])
    }
  }
  for (let i = 0; i < delCount; i++) {
    res.push(secondPart[i])
    delete secondPart[i]
  }
  const newlist = firstPart.concat(args).concat(secondPart.filter(item => item))
  newlist.forEach((item, index) => {
    this[index] = item
  })
  this.length = newlist.length
  return res
}

let arr1 = ['jk', 26, 'chrome', 'mac', 'win']
let arr2 = ['jk', 26, 'chrome', 'mac', 'win']
console.log(arr1.splice2(-2, 2), arr1)
console.log(arr2.splice(-2, 2), arr2)

jiangkuan2018 avatar Sep 21 '20 06:09 jiangkuan2018

Array.prototype._splice = function (start, deleteCount, ...addList) { if (start < 0) { if (Math.abs(start) > this.length) { start = 0 } else { start += this.length } } // 判断deleteCount 是否大于0 deleteCount = deleteCount > 0 ? deleteCount : 0 // 删除了的数组 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
}

chasegirls avatar Oct 15 '20 04:10 chasegirls

Array.prototype.splice = function (start = 0, number = 0, value) {
  const arr = [...this];
  const delArr = [];
  const range = start + number;
  this.length = 0;
  for (const [index, item] of arr.entries()) {
    if (index > range) {
      this.push(item);
    } else if (index === range) {
      if (value) {
        this.push(value);
      }
      this.push(item);
    } else {
      if (index < start) {
        this.push(item);
      } else {
        delArr.push(item);
      }
    }
  }
  return delArr;
};

cuizaiyong avatar Oct 15 '20 06:10 cuizaiyong

Object.defineProperty(Array.prototype, 'vsplice', {
    value: function (start, delCount, ...args) {
        if (this === null) {
            throw TypeError('对象不可为空');
        }

        var o = Object(this);
        if (arguments.length < 1) {
            throw TypeError('开始位置参数不能为空');
        }
        var len = o.length >>> 0;
        var argsLen = arguments.length;
        var k = 0;
        while (k < len && !(k in o)) {
            k++;
        }
        if (k >= len && argsLen < 3) {
            return [];
        }

        if (start > len) {
            return o;
        }
        var realStart = start;

        if (start < 0) {
            realStart = len + start;
        }
        if (realStart < 0) {
            realStart = 0;
        }

        var realCount = delCount;
        if (argsLen === 1) {
            realCount = len - realStart;
        }
        if (argsLen === 2 && delCount <= 0) {
            return o;
        }
        var other = new Array(realCount);
        if (realCount > 0) {
            k = realStart;            
            var otherK = 0;
            while (k < len && realCount > 0) {
                other[otherK++] = o[k];
                delete o[k];
                //o.length--;
                k++;
                realCount--;
            }
            if(argsLen<3){
                return other;
            }
            
        }

        len = o.length >>> 0;

        var inserts = Array.prototype.slice.call(arguments, 2);

        for (var i = 0; i < inserts.length; i++) {
            if (len === 0) {
                o[realStart++] = inserts[i];
            } else {
                var temp = o[realStart];
                o[realStart] = inserts[i];
                if(temp!== undefined){
                    o[1 + realStart] = temp;
                }                
                realStart ++;
            }
        }

        return other;
    }
});

vince-fly avatar Oct 30 '20 12:10 vince-fly

思路: 砍左中右三个部分,然后分别处理。

const arr = [1, 2, 12, 32, 43]
const after = arr.splice(-1, -2,33, 4);
console.log('答案 ---', arr, after);

const arr2 = [1, 2, 12, 32, 43];
function splice(list, start, deleteNum, ...addList) {
  const startIndex = start > 0 ? start : list.length - Math.abs(start);
  const endIndex = deleteNum > 0 ? startIndex + deleteNum : undefined;
  let left = [];
  let splice = [];
  let right = [].concat(addList);
  
  list.forEach((item, index) => {
    if (index < startIndex) left.push(item);
    if (index >= startIndex && endIndex === undefined) {
      right.push(item);
      return;
    }
    if (index >= startIndex && index < endIndex) splice.push(item);
    if (index >= endIndex) right.push(item);
  })
  list.length = 0;
  list.push(...left, ...right);
  return splice;
}

const newArr = splice(arr2, -1, -2,33, 4);
console.log('结果 ---', arr2, newArr);

hcc0007 avatar Nov 06 '20 16:11 hcc0007

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
      }

最短代码数😝

大佬 您这个是真的秀了!!秀的我眼花缭乱

hcc0007 avatar Nov 06 '20 16:11 hcc0007

100% mock Array.prototype.splice

Array.prototype._splice = function(index, cutNum, ...args) {
	const arr = this;
	const leftArr = arguments.length === 0 ? [] : arr.slice(0, index);
	const rightArr = arguments.length === 1 ? [] : arr.slice(index + (cutNum || 0));
	const changeArr = [...leftArr, ...args, ...rightArr];
	const result = arguments.length === 1 ? arr.slice(index) : arr.slice(index, index + cutNum)
	changeArr.forEach((val,index) => this[index] = val);	// change
	this.length = changeArr.length;
	return result;
}
//  test
var arr1 = [1,2,3,4,5,6,7];
var arr2 = [1,2,3,4,5,6,7];
console.log(arr1.splice(1,3,'a','b'));
console.log(arr1);
console.log(arr2._splice(1,3,'a','b'));
console.log(arr2);

JianJroh avatar Nov 26 '20 06:11 JianJroh

Array.prototype.splice = function (start, deleteCount, ...items) {
	if (start < 0) {
		start += this.length;
	}
	if (start < 0) start = 0;
	if (deleteCount == undefined) {
		deleteCount = this.length - start;
	} else if (deleteCount < 0) {
		deleteCount = 0;
	}
	const left = [].slice.call(this, 0, start);
	const deleted = [].slice.call(this, start, start + deleteCount);
	const right = [].slice.call(this, start + deleteCount);

	this.length = 0;
	this.push(...left, ...items, ...right);
	return deleted;
};

Luz-Liu avatar Feb 20 '21 07:02 Luz-Liu

Array.prototype.splice = function(start,deleteCount,...rest){
    let arr  = this;
    let deleteArr = [];
    // 如果第二个参数没有,说明从start删到最后
    if(deleteCount === undefined){
        deleteArr = arr.slice(start);
    }
    if(deleteCount >= 0){
        deleteArr = arr.slice(start, start + deleteCount);
        arr = arr.slice(0, start).concat(rest).concat(arr.slice(start + deleteCount))
    }
    // 修改原来数组
    arr.forEach((item,index) => this[index] = item);
    this.length = arr.length;
    return deleteArr;
}


yinhaiying avatar Feb 25 '21 09:02 yinhaiying

Array.prototype.splice2 = function(start, count, ...addList) {
    if (start < 0) {
        if (Math.abs(start) > this.length) {
            start = 0
        } else {
            start = this.length + start
        }
    }
    if (typeof count !== 'number') {
        count = this.length - start
    } else {
        if (count < 0) {
            count = 0
        }
    }
    let delList = this.slice(start, start + count)
    let right = this.slice(start + count, this.length)
    this.length = start
    this.push(...(addList.concat(right)))
    return delList
}

zhangfangbiao avatar Mar 03 '21 06:03 zhangfangbiao

Array.prototype.spliceLike = function(start, num, ...params) {
    return [...this.slice(0, start), ...params, ...this.slice(start + num)]
}

qzruncode avatar Apr 13 '21 09:04 qzruncode

    Array.prototype._splice = function (start, count, ...replaceEl) {
      if (typeof start !== "number") throw new Error("start not a number");
      if (typeof count !== "number") throw new Error("count not a number");
      start = start < 0 ? Math.max(start + this.length, 0) : start; // 开始值为负数要加上数组长度且不能小于零;
      Math.max(0, count); // 删除数量大于等于0;
      const delArr = this.slice(start, start + count);
      const resArr = [
        ...this.slice(0, start),
        ...replaceEl,
        ...this.slice(start + count),
      ];
      delArr.forEach((item, index) => {
        delete this[index];
      });
      resArr.forEach((item, index) => {
        this[index] = item;
      });
     this.length = resArr.length;
      return delArr;
    };

haipingzi avatar Apr 26 '21 05:04 haipingzi

Array.prototype.splice2 = function(start, count, ...addList) {
    if (start < 0) {
        if (Math.abs(start) > this.length) {
            start = 0
        } else {
            start = this.length + start
        }
    }
    if (typeof count !== 'number') {
        count = this.length - start
    } else {
        if (count < 0) {
            count = 0
        }
    }
    let delList = this.slice(start, start + count)
    let right = this.slice(start + count, this.length)
    this.length = start
    this.push(...(addList.concat(right)))
    return delList
}

const arr1 = [1, 2, 3, 4, 5]; const arr2 = [1, 2, 3, 4, 5]; arr1.splice2(100, 1, [1, 2]) arr2.splice(100, 1, [1, 2]) console.log(arr1) console.log(arr2) //大于数组长度就不正确了

haipingzi avatar Apr 26 '21 16:04 haipingzi

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
    }

sart 大于数组长度就不对了 const arr1 = [1, 2, 3, 4, 5]; const arr2 = [1, 2, 3, 4, 5]; arr1._splice(100, 1, [1, 2]) arr2.splice(100, 1, [1, 2]) console.log(arr1) //  [1, 2, 3, 4, 5, empty × 95, Array(2)] console.log(arr2) // [1, 2, 3, 4, 5, Array(2)]

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
    }

start大于数组长度就不对了

haipingzi avatar Apr 26 '21 16:04 haipingzi

Array.prototype.splice = function(index, num, ...rest) {
    let context = this
    let removeList = []
    //index为负值
    if (index < 0) {
        index = index + context.length
    }
    //num存在
    if(num != null) {
        if (num !== 0) {
            //查找要删除的元素
            for (let i = index; i < index + num; i++) {
                removeList.push(context[i])
            }
            //移除要移除的元素
            const conLength = context.length
            for (let i = index + num; i < conLength; i++) {
                context[i - num] = context[i]
            }
            context.length = conLength - num
        }
        //添加要添加的元素
        if (rest.length > 0) {
            const restLength = rest.length
            const conLength = context.length
            for(let i = conLength - 1; i >= index; i--) {
                context[i+restLength] = context[i]
            }
            
            let count = 0
            for(let i = index; i < index+restLength; i++) {
                context[i] = rest[count]
                count++
            }
        }
    } else {
        //查找要删除的元素
        const conLength = context.length
        for (let i = index; i < conLength; i++) {
            removeList.push(context[i])
        }
        context.length = index
    }
    return removeList
}
var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(2, 0, 'drum', 'guitar');

console.log(myFish)
console.log(removed)
//应该把数组第index位左移或右移n位抽象成函数,看起来应该就清楚多了

z1948296027 avatar May 15 '21 07:05 z1948296027

Array.prototype._splice = function (start, delCount, ...addItems) {
  const arr = this;
  const res = [];
  const left = arr.slice(0, start);
  const right = arr.slice(start + delCount)
  const remove = arr.slice(start, start + delCount); // 被删除的元素

  arr.length = left.length;
  addItems.forEach(item => arr.push(item));
  right.forEach(item => arr.push(item));
  return remove;
}

poppydani avatar Jul 09 '21 08:07 poppydani

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
    }

你这个有问题,当start不小于0却大于数组长度的时候你这个会错误的导致数组长度变大

Jobs-Chen avatar May 12 '22 06:05 Jobs-Chen

你的邮件我已收到,我会马上查看! —————————————————————— 现在的追逐梦想是为了日后能拥有美好的“那些年”!

listentolife avatar May 12 '22 06:05 listentolife

Array.prototype._splice = function(start, delCount, ...addList) {
    // 当起始位置超出了数组的长度,则从数组末尾开始添加内容
    if(start > this.length) {
        start = this.length;
        delCount = 0;
    }
    if(start < 0) {
        // 超出数组长度的话设置为0
        if(Math.abs(start) > this.length) {
            start = 0;
        } else {
            // 如果起始值为负数,则起始位置为数组末尾开始第几位
            start += this.length;
        }
    }
    // 设置删除的长度,没有值的话相当于移除起始位置之后的所有元素
    if(delCount === undefined) {
        delCount = this.length - start;
    }
    // 删除的元素
    const removeList = this.slice(start, start + delCount);
    // 删除元素的右侧数据
    const right = this.slice(start + delCount);

    // 将新加入的数据和右侧剩余的数据合并,然后将数组下标对应位置的元素替换
    let addStart = start;
    addList.concat(right).forEach(item => {
        this[addStart] = item;
        addStart++;
    });
    // 修改数组长度
    this.length = addStart;
    // 返回删除的元素
    return removeList;
}

这里附上MDN对于这个方法的定义Array.prototype.splice() 参数 start​ 指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。 deleteCount 可选 整数,表示要移除的数组元素的个数。如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)。如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除。如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。 item1, item2, ... 可选 要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。 返回值 由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。

Jobs-Chen avatar May 12 '22 06:05 Jobs-Chen

Array.prototype._splice = function (start, deleteCount, ...items) {
  if (start < 0) {
    start += this.length;
  }
  start = Math.max(start, 0);

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

  if (start >= this.length) {
    deleteCount = 0;
  }
  deleteCount = Math.max(deleteCount, 0);

  const length = this.length;
  const right = [];
  const deleted = [];

  for (let i = start + deleteCount; i < length; i++) {
    right.unshift(this.pop());
  }

  for (let i = start; i < start + deleteCount; i++) {
    deleted.unshift(this.pop());
  }

  for (let i = 0; i < items.length; i++) {
    this.push(items[i]);
  }

  for (let i = 0; i < right.length; i++) {
    this.push(right[i]);
  }

  return deleted;
};

lucaslmlok avatar Jun 20 '22 18:06 lucaslmlok

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

start
如果是负数,判断abs 值如果大于 length ,则 start置为 0 否则 start取 length-start 否则(非负数),直接取 start

deleteCount 要删除的个数 如果不指定,或 deleteCount>=length 则将 start 后的 数都删除 如果取值为0或负数,则不进行删除操作 否则删除 包含 start 及之后的 共 deleteCount 个数

item1,item2,...

要插入的元素

Yangfan2016 avatar Aug 18 '22 10:08 Yangfan2016

你的邮件我已收到,我会马上查看! —————————————————————— 现在的追逐梦想是为了日后能拥有美好的“那些年”!

listentolife avatar Aug 18 '22 10:08 listentolife