比较两个 Uint8Array 的相等性。

7

我正在使用CRC32比较两个Uint8Array,以确保解压缩的数据准确无误。然而,我面临的问题是没有像Uint8Array.equal()这样的API来比较数组。虽然在Node.js中有Buffer.compare()可用,但它不受浏览器支持,而我也在浏览器上工作。

我已经创建了一个基本实现,但我不确定是否有更简单的方法或者是否忽略了任何内置的比较API。

function isEqual(arr1: Uint8Array, arr2: Uint8Array): boolean {
    if (arr1.length !== arr2.length) {
        return false
    }

    return arr1.every((value, index) => value === arr2[index])
}

为什么不直接安装buffer,并像在Node.js中一样使用它呢? - Teneff
或者在这里检查它的.prototype.compare实现链接 - Teneff
感谢 @Teneff 的建议,我更喜欢使用本地API而非外部库来保持我的库的兼容性。 - Filip Seman
1
我不这么认为。这基本上是这个问题的重复,正如你所看到的,所有答案本质上都是相同的:检查长度并使用every - zenly
1
我理解它本质上是一个数组,因为它扩展了Iterator,但我希望有一个更具表现力的方法,就像Buffer.compareAPI一样。 - Filip Seman
2个回答

7

你没有错过任何东西,目前没有针对类型数组(或常规数组)的相等检查方法,或者可以简洁地使用一个同时保持大数组效率的东西。

一个提议存在,但似乎没有得到太多关注。 其中一个更具争议的问题是不应该为类型数组专门设置一个方法,而应该只有一个静态对象相等检查方法。

尚未有标准的对象相等检查方法,但過去已经提出了建议。这里是一个被撤回的建议。当然,你可以创建自己的函数,像这样,可能要特殊处理ArrayBuffer.isView,先比较length,再比较每个属性。这种函数有许多潜在的边界情况,也许这就是通用标准解决方案难以找到的原因。

目前最好的比较两个类型数组的方法是通过比较 length 并在您自己的函数中循环遍历值。您可以使用类似 every 的方法或简单的 for/while 循环来完成第二部分(简单循环可能更快,因为它的开销较小)。


1
function isEqualArray(a, b) { if (a.length != b.length) return false; for (let i = 0; i < a.length; i++) if (a[i] != b[i]) return false; return true; } - milahu

1

确实有一种方法可以比较两个已经内置到大多数浏览器中的Uint8Arrays:

function areBytewiseEqual(a, b) {
  return indexedDB.cmp(a, b) === 0;
}

如果 a 和/或 b 是 ArrayBuffers 或 DataViews,这也可以工作。

(这是一个奇怪的 API,只为此功能而存在,并且它并不是该方法的直接意图 - 但根据我阅读规范的结果,没有逻辑上的理由不以这种方式使用它。)


你可能想要链接https://developer.mozilla.org/en-US/docs/Web/API/IDBFactory/cmp,并引用免责声明:“*不要使用此方法来比较任意的JavaScript值,...*” - 当然,一个类型化数组是一个只包含数值元素的数组,所以它确实可以正常工作。 - Bergi
@Bergi 自从 IndexedDB 2.0 版本以来,API 已经支持了“二进制”键 https://w3c.github.io/IndexedDB/#key-construct ,这些键是“ArrayBuffer 对象(或者是像 Uint8Array 这样的缓冲区视图)”,所以这并不是将类型化数组当作数字数组处理的情况,而是通过比较算法特殊处理的。 - denzquix
有趣!不过有几个值得注意的事情:1. 目前这是一个浏览器 API,所以在 node 或 deno 中无法原生使用。2. 不同类型可能会出现一些意外情况,比如:indexedDB.cmp(new Uint8Array([255]), new Int8Array([-1])) === 0indexedDB.cmp(new Uint8Array([0, 0]), new Int16Array([0])) === 0(并没有错,但对于不了解内部运作的人可能会感到困惑)。 - Alexander O'Mara
@AlexanderO'Mara 是的,确实如此,甚至有一些边缘情况,同一类型可能会产生令人惊讶的结果:indexedDB.cmp(new Float64Array([0]), new Float64Array([-0])) !== 0 - denzquix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接