Duplicate Priority Filtering (v2)

Revision 2 of this benchmark created on


Description

Filtering the highest priority duplicate from a list of duplicate json objects (duplicated on primary key)

Setup

// Generate ~Dynamics-style GUID
function generateGuid() {
  if (typeof crypto !== "undefined" && crypto.randomUUID) {
    return crypto.randomUUID(); // native, good randomness
  }

  // Fallback: 8-4-4-4-12 hex pattern
  const hex = () => Math.floor(Math.random() * 0x10000).toString(16).padStart(4, "0");
  return (
    hex() + hex() + "-" +
    hex() + "-" +
    hex() + "-" +
    hex() + "-" +
    hex() + hex() + hex()
  );
}

function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

// Fisher–Yates shuffle
function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}

function generateItems(count = 40000) {
  const items = [];
  const usedKeys = new Set();

  const getUniqueGuid = () => {
    let id;
    do {
      id = generateGuid();
    } while (usedKeys.has(id));
    usedKeys.add(id);
    return id;
  };

  while (items.length < count) {
    const remaining = count - items.length;

    // how many times this primaryKey will appear (1–4, but not exceeding remaining slots)
    const occurrences = Math.min(remaining, randomInt(1, 4));

    const primaryKey = getUniqueGuid();

    // pick unique priorities 1–4, no duplicates per key
    const priorities = shuffle([1, 2, 3, 4]).slice(0, occurrences);

    for (let i = 0; i < occurrences; i++) {
      items.push({
        primaryKey,
        priority: priorities[i]
      });
    }
  }

  // Randomise final order
  shuffle(items);

  return items;
}

// Example usage:
const baseItems = generateItems(40000);

Test runner

Ready to run.

Testing in
TestOps/sec
Double Sort
// Sort first (primaryKey then priority), then check if primaryKey has changed and push first of each group

const items = baseItems.slice();   // keep this if you need to preserve baseItems
const highest = [];

// Faster comparator: plain string compare instead of localeCompare
items.sort((a, b) => {
  const keyA = a.primaryKey;
  const keyB = b.primaryKey;

  if (keyA < keyB) return -1;
  if (keyA > keyB) return 1;

  // keys equal → sort by priority (ascending)
  return a.priority - b.priority;   // flip sign if you want highest number first
});

// Single pass, tight loop
let lastKey = null;

for (let i = 0, len = items.length; i < len; i++) {
  const obj = items[i];
  const key = obj.primaryKey;

  if (key !== lastKey) {
    highest.push(obj);   // first (lowest-priority) for this key in sorted group
    lastKey = key;
  }
}
ready
ChatGPT Oneshot (Simple Map)
//Loop over items, check if key already exists, then check if current item is higher or lower, then write to dict
// Create a map of key → max priority
const items = baseItems.slice();
const map = {};

for (const obj of items) {
  const key = obj.primaryKey;
  const value = obj.priority;

  if (!(key in map) || value < map[key]) {
    map[key] = obj;   // keep highest priority
  }
}

// Convert back to array of objects in the new structure
const highest = Object.values(map);
ready
Sort first, compare, then write to dict
const items = baseItems.slice();
const map = new Map();

items.sort((a, b) => a.priority - b.priority); // or reverse, depending on priority semantics

for (const obj of items) {
  const key = obj.primaryKey;

  if (!map.has(key)) {
    map.set(key, obj);  // first occurrence of this key in sorted order
  }
}

const highest = [...map.values()];
ready
ChatGPT (Improve it)
const items = baseItems.slice();
const highestMap = new Map();

for (const obj of items) {
  const key = obj.primaryKey;
  const existing = highestMap.get(key);

  // flip < / > depending on whether lower number = higher priority
  if (existing === undefined || obj.priority < existing.priority) {
    highestMap.set(key, obj);
  }
}

const highest = [...highestMap.values()];
ready
ChatGPT (Improve it AGAIN)
const items = baseItems.slice();
const highestMap = new Map();

for (let i = 0, len = items.length; i < len; i++) {
  const obj = items[i];
  const key = obj.primaryKey;
  const existing = highestMap.get(key);

  // lower number = higher priority (flip sign if your semantics differ)
  if (existing === undefined || obj.priority < existing.priority) {
    highestMap.set(key, obj);
  }
}

const highest = Array.from(highestMap.values());
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.