JS数组面试题——拆分数组

JS Array Interview Question - Split Array

我在一次面试中遇到了这个问题,并被告知我有 20 分钟的时间来解决它。这是我想出的答案(2 个版本)。你能告诉我你更喜欢哪个版本吗?为什么,如果你对如何解决它有更好的想法(不那么复杂,更少的内存使用等)请分享。

问题:你有一个随机数数组,范围从 0 到 100 个元素。

  1. 编写一个函数将此数组拆分为多个数组,每个数组包含以下范围内的元素:(0-10],(10-20],(20-30], 等等到 100].

  2. 编写一个函数,以简单图形的形式输出这些数组,其中每个分隔符代表数组中的一个值。

Array = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];


期望的结果:

5  Elements in array: *****  -  1,5,6,3,4 
3  Elements in array: ***  -  10,12,11 
2  Elements in array: **  -  22,21 
No Elements in array. 
2  Elements in array: **  -  45,42 
3  Elements in array: ***  -  52,51,55 
2  Elements in array: **  -  64,65 
1  Elements in array: *  -  71 
No Elements in array. 
2  Elements in array: **  -  95,99 

// Version 1
arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];

const splitArray = (inputArray, range) => {
  const newArray = [];
  do {
    let tempArray = [];
    tempArray = inputArray.filter((item) => {
      if (item >= range && item < range + 10) return item;
    });
    range += 10;
    newArray.push(tempArray);
  } while (range + 10 <= 100);
  return newArray;
};

const printArrays = (array, delimiter) => {
  let toPrint = "";
  for (index in array) {
    let stars = array[index].length;
    let string = "";
    for (let i = stars; i > 0; i--) {
      string += delimiter;
    }
    toPrint += stars
      ? `${stars}  Elements in array: ${string}  -  ${array[index]} \n`
      : "No Elements in array. \n";
  }
  return toPrint;
};

console.log(printArrays(splitArray(arr, 0), "*"));

// Version 2
arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];

const getArrays = (inputArray) => {
  const newArray = [];
  let min = 0;
  let max = 10;
  do {
    const tempArray = [];
    for (i in arr) {
      let val = arr[i];
      val >= min && val < max ? tempArray.push(val) : "";
    }
    min += 10;
    max += 10;
    newArray.push(tempArray);
  } while (max <= 100);
  return newArray;
};

const printArrays = (array, delimiter) => {
  for (index in array) {
    let stars = array[index].length;
    let string = "";
    for (let i = stars; i > 0; i--) {
      string += delimiter;
    }
    console.log(
      stars ? `${stars}  Elements in array: ${string}  -  ${array[index]}` : "No Elements in array."
    );
  }
};

printArrays(getArrays(arr), "^");

两种方法都有中等问题。


第一种方法可以

let tempArray = [];
tempArray = inputArray.filter((item) => {
  if (item >= range && item < range + 10) return item;
});

最好只将 tempArray 声明为过滤后的数组。

const tempArray = inputArray.filter(...

此外,return itemfilter 中是可疑的 - 所有过滤器回调关心的是它的 return 值是真还是假。当您实际上想要指示该值应包含在输出中时返回数组项是一个常见错误。 碰巧 在这里不是问题,因为 0 是不可能的,但它仍然令人困惑。更好的选择是做

const tempArray = inputArray.filter(
  item => item >= range && item < range + 10
);

(并可能将 range 重命名为 startOfRange


您的两种方法还多次遍历整个输入数组(每个范围一次),这似乎有点浪费 - 最好遍历输入 一次


您的第二种方法使用 for (i in arr),并且两种方法都在做 for (index in array)。这是一个 bad idea,由于您实际上并不关心要迭代的索引,因此使用 for..of 循环是有意义的。


我认为只遍历输入一次的更好看的方法是:

const arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];

const getArrays = (inputArray) => {
  const grouped = {};
  for (let i = 0; i < 100; i += 10) {
    grouped[i] = [];
  }
  for (const item of inputArray) {
    const rangeProp = Math.floor(item / 10) * 10;
    grouped[rangeProp].push(item);
  }
  return Object.values(grouped);
};

const printArrays = (groupedArrays, delimiter) => {
  for (const array of groupedArrays) {
    const stars = delimiter.repeat(array.length);
    console.log(
      stars
        ? `${array.length}  Elements in array: ${stars}  -  ${array.join(',')}`
        : "No Elements in array."
    );
  }
};

printArrays(getArrays(arr), "*");

我会这样做:

这种方法很简单:它一个一个地检索值,并将它们添加到与其范围对应的数组中。

const arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];


let ranges = arr.reduce((a,x)=>
  {
  let range = (x/10)|0  // get range start value 0 to 9
  a[range] ??= []       // create the array of if it does not already exist
  a[range].push(x) 
  return a
  },{})

console.log('ranges=', ranges ) // so that noobs can visualize this result

for (let r = 0; r < 10; r++ )
  {
  if (!ranges[r])
    document.write('No Elements in array.<br>')
  else
    {
    let count = ranges[r].length
    document.write(`${count} Elements in array: ${'*'.repeat(count)} - ${ranges[r].join(',')}<br>`)
    }
  }
.as-console-wrapper {max-height: 100% !important; width:20%; top: 0;
margin-left: 80%;  }
.as-console-row::after {display: none !important;}
 

range = (x/10)|0  // get range start value 0 to 9

示例 x = 25 -> 25/10 给出 2.52.5 | 0 给出 2 -> 2.5 的整数部分值

| 是 OR 布尔运算符,仅适用于整数值,因此它 return 是一个整数

??=Logical nullish assignment