npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tpmjs/tools-dedupe-by-key

v0.2.0

Published

Remove duplicate objects from an array based on one or more key fields

Downloads

54

Readme

@tpmjs/tools-dedupe-by-key

Remove duplicate objects from an array based on one or more key fields.

Features

  • Single or composite keys: Dedupe by one field or multiple fields combined
  • Keep first or last: Choose which occurrence to preserve
  • Nested field support: Use dot notation to access nested properties
  • Detailed statistics: Returns count of duplicates removed and unique rows
  • Type-safe: Handles various data types in key fields (strings, numbers, objects)

Installation

npm install @tpmjs/tools-dedupe-by-key ai

Usage

import { dedupeByKeyTool } from '@tpmjs/tools-dedupe-by-key';
import { generateText } from 'ai';

const result = await generateText({
  model: yourModel,
  tools: {
    dedupeByKey: dedupeByKeyTool,
  },
  prompt: 'Remove duplicate users by email address',
});

Parameters

  • rows (array, required): Array of objects to deduplicate
  • key (string | string[], required): Field name(s) to use as unique key
    • Single field: "email"
    • Multiple fields: ["firstName", "lastName"]
    • Nested fields: "user.email" or ["user.id", "account.type"]
  • keepLast (boolean, optional): If true, keeps last occurrence; if false (default), keeps first

Returns

{
  rows: Record<string, unknown>[],  // Deduplicated array
  duplicatesRemoved: number,         // Number of duplicates removed
  originalCount: number,             // Original array length
  uniqueCount: number               // Deduplicated array length
}

Examples

Simple deduplication by single field

const users = [
  { id: 1, email: '[email protected]', name: 'Alice' },
  { id: 2, email: '[email protected]', name: 'Bob' },
  { id: 3, email: '[email protected]', name: 'Alice Updated' },
];

// Keep first occurrence (default)
// Returns: { rows: [Alice, Bob], duplicatesRemoved: 1, ... }
await dedupeByKeyTool.execute({
  rows: users,
  key: 'email',
});

// Keep last occurrence
// Returns: { rows: [Bob, Alice Updated], duplicatesRemoved: 1, ... }
await dedupeByKeyTool.execute({
  rows: users,
  key: 'email',
  keepLast: true,
});

Composite key (multiple fields)

const events = [
  { userId: 1, action: 'login', timestamp: '2024-01-01T10:00:00Z' },
  { userId: 1, action: 'login', timestamp: '2024-01-01T10:05:00Z' },
  { userId: 1, action: 'logout', timestamp: '2024-01-01T11:00:00Z' },
  { userId: 2, action: 'login', timestamp: '2024-01-01T10:00:00Z' },
];

// Dedupe by userId AND action
// Returns: { rows: [user1-login, user1-logout, user2-login], duplicatesRemoved: 1, ... }
await dedupeByKeyTool.execute({
  rows: events,
  key: ['userId', 'action'],
});

Nested field deduplication

const orders = [
  { id: 1, customer: { email: '[email protected]' }, total: 100 },
  { id: 2, customer: { email: '[email protected]' }, total: 200 },
  { id: 3, customer: { email: '[email protected]' }, total: 150 },
];

// Dedupe by nested field
// Returns: { rows: [order1, order2], duplicatesRemoved: 1, ... }
await dedupeByKeyTool.execute({
  rows: orders,
  key: 'customer.email',
});

Keep last occurrence use case

const stockPrices = [
  { symbol: 'AAPL', price: 150.0, timestamp: '2024-01-01T09:00:00Z' },
  { symbol: 'GOOGL', price: 140.0, timestamp: '2024-01-01T09:00:00Z' },
  { symbol: 'AAPL', price: 152.0, timestamp: '2024-01-01T10:00:00Z' },
  { symbol: 'AAPL', price: 151.0, timestamp: '2024-01-01T11:00:00Z' },
];

// Get most recent price for each symbol
// Returns: { rows: [GOOGL@140, AAPL@151], duplicatesRemoved: 2, ... }
await dedupeByKeyTool.execute({
  rows: stockPrices,
  key: 'symbol',
  keepLast: true,
});

Use Cases

  • User deduplication: Remove duplicate user records by email or ID
  • Event deduplication: Eliminate duplicate events in logs
  • Data merging: Keep latest version when merging datasets
  • Cache invalidation: Ensure unique cache keys
  • Form submissions: Remove duplicate form entries

Handling Edge Cases

  • null/undefined values: Treated as distinct values in keys
  • Objects in key fields: Converted to JSON strings for comparison
  • Missing fields: Treated as undefined in the key
  • Empty arrays: Returns empty result with zero duplicates removed

License

MIT