Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 81 期(数据结构-数组):数组项的互换和移动 #84

Open
wingmeng opened this issue Aug 8, 2019 · 0 comments
Open

第 81 期(数据结构-数组):数组项的互换和移动 #84

wingmeng opened this issue Aug 8, 2019 · 0 comments

Comments

@wingmeng
Copy link
Collaborator

wingmeng commented Aug 8, 2019

数组是一种由有序的元素序列组成的集合,每个元素在数组中有一个位置,以数字表示,称为索引。
那么如何对数组项的位置进行移动操作?如何实现两个数组项的位置互换?

思路:

数组项的位置移动本质上是相邻数组项的位置互换(数组边界的情况除外),例如下面的数组:

['A', 'B', 'C', 'D'];  // 原数组
['A', 'C', 'B', 'D'];  // 将 C 向前移动一位

我们将 C 向前移动 1 位,本质上就是 B 和 C 互换了位置。那么如何实现位置互换?可以使用临时变量存储 B,然后从数组中删除 B,再将 B 插入到 C 的后面;或者用 ES6 的结构赋值,临时变量都省了,非常方便。
下面我们来看下具体实现。

/**
 * 交换数组项
 * @param {array} arr - 源数组
 * @param {number} srcIdx - 要交互位置的源数组项索引
 * @param {number} targetIdx - 目标位置索引
 */
function swapArrItem(arr, srcIdx, targetIdx) {
  if (!Array.isArray(arr)) {
    throw Error(`\`${arr}\` is not a array`);
  }

  if (isNaN(srcIdx) || isNaN(targetIdx)) {
    throw Error(`index is not a number`);
  }

  let len = arr.length - 1;

  // 边界情况判断
  srcIdx = srcIdx < 0 ? 0 : srcIdx;
  srcIdx = srcIdx > len ? len : srcIdx;
  targetIdx = targetIdx < 0 ? 0 : targetIdx;
  targetIdx = targetIdx > len ? len : targetIdx;

  arr = [...arr];
  [arr[srcIdx], arr[targetIdx]] = [arr[targetIdx], arr[srcIdx]];  // 解构赋值

  return arr;
}

/**
 * 移动数组项
 * @param {array} arr - 源数组
 * @param {number} idx - 要移动的源数组项索引
 * @param {string} method - 移动方式:
      1. first - 移动到数组最前
      2. last - 移动到数组最后
      3. forward - 向前移动1位
      4. backward - 向后移动1位
 */
function moveArrItem(arr, idx, method) {
  const _toBoundary = (arr1, idx, handle) => {
    let temp = arr1.splice(idx, 1)[0];

    arr1[handle](temp);
    return arr1;
  };

  if (!Array.isArray(arr)) {
    throw Error(`\`${arr}\` is not a array`);
  }

  arr = [...arr];

  switch(method) {
    case 'first':
      return _toBoundary(arr, idx, 'unshift');
    case 'last':
      return _toBoundary(arr, idx, 'push');
    case 'forward':
      return swapArrItem(arr, idx, idx - 1);
    case 'backward':
      return swapArrItem(arr, idx, idx + 1);
    default:
      throw Error(`${method} is not a available parameter`);
  }
}

测试用例:

let testArr = [0, 1, 2, 3, 4, 5];

console.log('原数组', testArr);
console.log('交换下标1和2项的位置', swapArrItem(testArr, 1, 2));
console.log('交换下标0和3项的位置', swapArrItem(testArr, 0, 3));
console.log('交换下标-5和9项的位置(越界测试)', swapArrItem(testArr, -5, 9));

console.log('将下标2项移动到最前', moveArrItem(testArr, 2, 'first'));
console.log('将下标2项移动到最后', moveArrItem(testArr, 2, 'last'));
console.log('将下标2项向前移动1位', moveArrItem(testArr, 2, 'forward'));
console.log('将下标2项向后移动1位', moveArrItem(testArr, 2, 'backward'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant