具有默认值的打字稿固定数组

Posted

技术标签:

【中文标题】具有默认值的打字稿固定数组【英文标题】: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 但它引用了与我正在执行对象数组相同的对象 这解决了固定长度数组:***.com/questions/41139763/… - 但是,不解决数组元素替换功能 - 您需要自己构建它。 我不认为你可以用一个普通的数组来做到这一点。您需要创建一个自定义类或函数。 数组不是这样工作的。您可以考虑使用循环缓冲区:en.wikipedia.org/wiki/Circular_buffer 我建议实现你自己的实现。第二条评论中提出的想法之一。 【参考方案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 的原因 欢迎您编辑我的答案并改进它。你有足够的代表。 ? 我留个便条是为了为未来的读者确定一个潜在的问题,而不是因为我希望你改变一些东西。教人们如何捕捉错误已经超出了这个问题的范围。

以上是关于具有默认值的打字稿固定数组的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:创建具有相同键但不同值的对象

具有定义值的打字稿动态对象键

特定字符串值的打字稿数组

具有基于变量的标签值的打字稿匿名对象

两个布尔值的打字稿元组被推断为布尔类型的数组

如何在 Angular 5 或打字稿中检索下面提到的 json 中具有错误值的键