【问题标题】:Typescript fixed array with default values具有默认值的打字稿固定数组
【发布时间】:2021-11-10 18:19:08
【问题描述】:

寻找一种方法来创建固定大小为 3 的对象数组,并用默认值填充它,但是当我推入数组时,它应该替换默认值。

示例

声明一个数组,用“默认值”字符串填充数组

["default value", "default value", "default value"]

我现在将一些文本推送到这个初始数组并期待以下内容:

["Added Data", "Default value", "Default Value"]

我将更多数据推送到此数组并期望以下内容:

["Added Data", "Added Data", "Default Value"]

我再次将更多数据推送到此数组并期待以下内容:

["Added Data", "Added Data", "Added Data"]

所以最终结果应该是如果推送一个数据,那么数组的其余部分应该保持默认值,除非我将所有三个数据都推送到数组中。

注意:这个例子是一个字符串数组,只是为了展示一个例子,但我正在寻找的解决方案是对象数组。 Array.fill() 方法适用于 JavaScript 不可变值,如字符串、数字和布尔值。带有对象的数组,数组中的每个插槽都引用同一个对象,这不是我要找的。我希望每个对象都是独一无二的

【问题讨论】:

  • Array.fill 但它引用了与我正在执行对象数组相同的对象
  • 这解决了固定长度数组:stackoverflow.com/questions/41139763/… - 但是,不解决数组元素替换功能 - 您需要自己构建它。
  • 我不认为你可以用一个普通的数组来做到这一点。您需要创建一个自定义类或函数。
  • 数组不是这样工作的。您可以考虑使用循环缓冲区:en.wikipedia.org/wiki/Circular_buffer
  • 我建议实现你自己的实现。第二条评论中提出的想法之一。

标签: javascript typescript


【解决方案1】:

您可以扩展 Array 类以使其具有您描述的行为...

class FixedArray extends Array {

  /**
   * Contruct a fixed-length Array
   * @param int length - length of the array
   * @param mixed default_value - The default value for empty slots
   */
  constructor(length, default_value) {
    super(length);
    this.default_value = default_value;
    super.fill(default_value);
  }

  /**
   * "Push" items onto the begining of the array (unshift)
   * @params ...args mixed - values to put in the array
   */
  push(...args) {
    args.forEach(arg => {
      super.pop();
      super.unshift(arg);
    });
  }

  /**
   * Pop an item off the end of the array 
   * and replace it with the default value
   */
  pop(){
    super.pop();
    super.push(this.default_value);
  }

  /**
   * Shift an item off the start of the array 
   * and replace it with the default value
   */
  shift(){
    super.shift();
    super.unshift(this.default_value);
  }

}

var arr = new FixedArray(4, 'default value');
console.log(arr);

arr.push('new value');
console.log(arr);

arr.push('new value');
console.log(arr);

arr.pop();
console.log(arr);

为了解决有关数组填充方法的部分,您可以添加一个方法来复制您放入其中的任何值...

/**
 * Fill the array with copies of whatever arguments are provided.
 * Fills by value, not by reference.
 */
fill(...args){
  args.forEach(arg=>{
    let copy = JSON.parse(JSON.stringify(arg));
    this.push(arg);
  });
}

【讨论】:

    【解决方案2】:

    使用默认唯一对象值创建和填充数组:

    const tuple = new Array(3).fill(0).map(() => ({ foo: "bar" }))
    
    // or
    const defaultObject = { foo: "bar" }
    const tuple = new Array(3).fill(0).map(() => ({ …defaultObject }))
    

    添加新项目,并保持数组大小不变

    function addTo(tuple, newItem) {
      tuple.unshift(newItem) // add new item to beginning 
      tuple.pop() // remove old item at the end
    }
    

    【讨论】:

    • 只有在对要填充的对象进行硬编码时才有效。如果您尝试使用存储在变量中的对象填充它,这将与将变量传递给填充方法完全相同。
    • 编辑是一种改进,但该默认对象中的任何嵌套对象仍将通过引用传递。
    • 已更新以使其更加明显。 OP 不想要相同的 ref,所以 .fill 不起作用,这就是我使用 .map 的原因
    • 欢迎您编辑我的答案并改进它。你有足够的代表。 ?
    • 我留个便条是为了为未来的读者确定一个潜在的问题,而不是因为我希望你改变一些东西。教人们如何捕捉错误已经超出了这个问题的范围。
    猜你喜欢
    • 2019-11-25
    • 2023-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 2019-04-21
    • 2018-04-17
    相关资源
    最近更新 更多