使用 JavaScript 对 2800 万个字符串进行重复数据删除

Kir*_*met 12 javascript arrays string object

我有一个包含 2800 万个字符串的 JSON 文件,大小约为 15 GB。有些字符串是重复的,因此我需要创建一个仅包含唯一字符串的新 JSON 文件。我猜其中有 2.4 亿个是独一无二的,但我需要找出确切的数字。这些字符串均小于 100 个字符。以下是数据示例:

[
    '4zWMS2IHAKcsrVtrUBFXIFjkwvbiCyiK',
    'btFqRsglI1Dh81jpgmnRhKPGIBbe2cU7',
    '8Us6mE6zWfyOpjhXsJssE65LrOFc7yr6',
    ...
]
Run Code Online (Sandbox Code Playgroud)

我的第一个方法是创建一个 JavaScript 对象并将该对象的所有键设置为字符串。然后我会检查密钥的长度,这将是我的唯一计数。不幸的是,我遇到了限制,JavaScript 对象只能有大约 8M 个键。

我的下一个方法是在 JavaScript 中创建一个新数组,然后迭代我的字符串,然后使用.indexOf方法查看是否已将字符串添加到数组中。不幸的是,这太慢了。

谁能想到一种方法可以在 JavaScript 中做到这一点?如果这不是适合这项工作的工具,我也可以切换到其他语言。

Kir*_*met 6

电脑都疯了。我受到评论的启发,将许多对象的键分片,这样我就不会达到 JavaScript 中 8M 的键限制。然后,我使用 GitHub Copilot 在大约 30 秒内编写了这段代码,仅使用注释并让 Copilot 编写其余部分:

// Find the files we want to count
let files = NodeFileSystem.readdirSync('data/imported');
let keyArray = [];
let keyArrayLength = 0;

// Add all of the keys to an array
for(let file of files) {
    if(file.endsWith('.json')) {
        console.log('Parsing file', file);
        let data = JSON.parse(NodeFileSystem.readFileSync('data/imported/'+file));

        // Add the data item.key to the array
        for(let item of data) {
            keyArray.push(item.key);
            keyArrayLength++;
        }
    }
}
console.log('Total array length:', keyArrayLength);

// JavaScript will only allow us to have 8 million keys in an object, so we need to shard the array
// into several objects, using the first characters of each key
let characterCountToUseForSharding = 2;

// An object to store the sharded objects
let shardedObjects = {};

// Loop through the key array
let processedCount = 0;
for(let key of keyArray) {
    processedCount++;
    if(processedCount % 1000000 === 0) {
        let processCountWithCommas = processedCount.toLocaleString();
        console.log('Processed', processCountWithCommas, 'of', keyArrayLength.toLocaleString());
    }

    // Get the first characterCountToUseForSharding characters of the key
    let shardingKey = key.substring(0, characterCountToUseForSharding);

    // If the sharded object doesn't exist, create it
    if(!shardedObjects[shardingKey]) {
        shardedObjects[shardingKey] = {};
        // console.log('Created sharded object', shardingKey);
    }

    // Add the key to the sharded object
    shardedObjects[shardingKey][key] = true;
}

// Count the keys in each sharded object
let total = 0;
for(let shardingKey in shardedObjects) {
    let keyCount = Object.keys(shardedObjects[shardingKey]).length;
    console.log('Sharding key', shardingKey, 'has', keyCount, 'keys');
    total += keyCount;
}

// Log the total
console.log('Total keys:', keyArrayLength);
console.log('Total unique keys:', total);

// Percentage
let percentage = (total / keyArrayLength) * 100;
console.log('Unique percentage:', percentage);

// Duplicate keys
let duplicateKeys = keyArrayLength - total;
console.log('Duplicate keys:', duplicateKeys);
Run Code Online (Sandbox Code Playgroud)

在这里您可以看到输出和速度:

https://www.youtube.com/watch?v=RurzxMjbazg

我在 M1 MacBook Pro 上运行它,对其速度感到惊讶。风扇甚至没有打开。

  • 您的视频显示数组长度为“28335100”,即 2800 万,甚至还不到 2.5 亿? (3认同)
  • `keyArrayLength`,真的吗?当您验证它生成的解决方案比自己编写代码花费更长的时间时,Copilot 似乎并不合适。 (2认同)