Descrição Overview Descripción
Duplicatas em texto podem parecer um problema menor, mas qualquer pessoa que já precisou limpar uma lista de e-mails, consolidar imports de TypeScript ou processar logs de servidor sabe o quanto elas atrasam. A lógica por trás da remoção de duplicatas é elegante: cria-se um conjunto (Set) que registra quais linhas já foram vistas; ao encontrar uma linha nova, ela vai para a saída; ao encontrar uma repetição, ela é silenciosamente descartada.
A escolha de manter a primeira ocorrência e não a última é deliberada. Na maioria dos casos de uso, a ordem original do documento tem significado: a primeira importação de uma dependência geralmente define o escopo, a primeira ocorrência de um endereço em uma lista consolidada costuma ser a mais confiável. Inverter a lógica e manter a última ocorrência é trivial, mas exige intenção consciente.
O detalhe que muda tudo é a estratégia de comparação: duas linhas com o mesmo conteúdo mas capitalização diferente são duplicatas? admin e Admin referem-se à mesma coisa em um arquivo de configuração? E a versão com espaços nas bordas? Para isso existem as opções de comparação case-insensitive e de trim antes de comparar. A linha exibida na saída é sempre a versão original da primeira ocorrência — a normalização acontece apenas durante a comparação, sem alterar o conteúdo.
Em bases de dados, o equivalente é o SELECT DISTINCT ou o GROUP BY. Em linguagens funcionais, é o nub de Haskell. Em Python, é o famoso dict.fromkeys(). Todos resolvem o mesmo problema com a mesma ideia central: um hash do valor como chave de um dicionário visitado.
Duplicates in text might seem like a minor annoyance, but anyone who has ever cleaned up an email list, consolidated TypeScript imports, or processed server logs knows how much they slow things down. The logic behind line deduplication is elegant: a Set tracks which lines have already been seen; when a new line appears, it goes to the output; when a repeat is found, it is silently discarded.
Keeping the first occurrence rather than the last is a deliberate choice. In most use cases, the original document order carries meaning: the first import of a dependency usually defines the scope, the first occurrence of an address in a consolidated list is typically the most reliable one. Reversing the logic to keep the last occurrence is trivial, but it requires conscious intent.
The detail that changes everything is the comparison strategy: are two lines with the same content but different casing duplicates? Are admin and Admin the same thing in a config file? What about the version with surrounding spaces? That is why case-insensitive comparison and trim-before-compare options exist. The line written to the output is always the original version of the first occurrence — normalization happens only during comparison and does not alter the content.
In databases, the equivalent is SELECT DISTINCT or GROUP BY. In functional languages, it is Haskell's nub. In Python, it is the classic dict.fromkeys(). All solve the same problem with the same core idea: a hash of the seen value as a key in a visited dictionary.
Los duplicados en texto pueden parecer un problema menor, pero cualquiera que haya limpiado una lista de correos electrónicos, consolidado imports de TypeScript o procesado logs de servidor sabe cuánto ralentizan el trabajo. La lógica detrás de la eliminación de líneas duplicadas es elegante: se crea un Set que registra qué líneas ya se han visto; cuando aparece una línea nueva, va a la salida; cuando se encuentra una repetición, se descarta silenciosamente.
Mantener la primera aparición en lugar de la última es una decisión deliberada. En la mayoría de los casos de uso, el orden original del documento tiene significado: el primer import de una dependencia generalmente define el ámbito, la primera aparición de una dirección en una lista consolidada suele ser la más fiable. Invertir la lógica para mantener la última aparición es trivial, pero requiere una intención consciente.
El detalle que lo cambia todo es la estrategia de comparación: ¿son duplicados dos líneas con el mismo contenido pero distinta capitalización? ¿Son lo mismo admin y Admin en un archivo de configuración? ¿Y la versión con espacios alrededor? Por eso existen las opciones de comparación sin distinción entre mayúsculas y minúsculas y de trim antes de comparar. La línea escrita en la salida es siempre la versión original de la primera aparición: la normalización ocurre solo durante la comparación y no altera el contenido.
En bases de datos, el equivalente es SELECT DISTINCT o GROUP BY. En lenguajes funcionales, es el nub de Haskell. En Python, es el clásico dict.fromkeys(). Todos resuelven el mismo problema con la misma idea central: un hash del valor como clave en un diccionario visitado.
Detalhamento técnico
Casos de uso comuns
- Listas de dependências: arquivos requirements.txt, package.json ou pom.xml que cresceram ao longo do tempo frequentemente acumulam entradas duplicadas vindas de merges e copias manuais.
- Imports e diretivas de código: consolidar arquivos de TypeScript, Python ou C# de várias origens costuma produzir imports repetidos que o compilador aceita mas que poluem o código.
- Endereços e cadastros: listas de e-mail, telefones ou CPFs exportadas de sistemas diferentes chegam cheias de entradas duplicadas com variações sutis de capitalização.
- Logs de servidor: ao concatenar logs de múltiplos períodos para análise, linhas idênticas de aviso ou erro se repetem centenas de vezes e obscurecem os eventos únicos.
- Arquivos de configuração: opções de configuração duplicadas podem causar comportamentos inesperados dependendo de qual ocorrência o parser usa.
Modos de comparação
- Comparação exata (padrão): duas linhas são duplicatas somente se forem byte a byte idênticas. A linha de saída preserva a capitalização e os espaços originais.
- Case-insensitive: converte ambas as linhas para minúsculas antes de comparar. Útil para listas de nomes, endereços e identificadores que podem vir com capitalização inconsistente.
- Trim antes de comparar: remove espaços e tabs das bordas antes de verificar se a linha já foi vista. A linha de saída ainda exibe o conteúdo original com os espaços, mas o critério de duplicata ignora o recuo.
- Combinação de case-insensitive e trim: o modo mais permissivo, que trata variantes com espaços extras e capitalização diferente como a mesma linha.
Technical deep dive
Common use cases
- Dependency lists: requirements.txt, package.json, or pom.xml files that grew over time often accumulate duplicate entries from merges and manual copy-pastes.
- Code imports and directives: consolidating TypeScript, Python, or C# files from multiple sources typically produces repeated imports that compile fine but pollute the codebase.
- Address and contact lists: email, phone, or ID lists exported from different systems arrive full of duplicates with subtle casing variations.
- Server logs: concatenating logs from multiple time periods for analysis causes identical warning or error lines to repeat hundreds of times and obscure unique events.
- Config files: duplicate configuration options can cause unexpected behavior depending on which occurrence the parser uses.
Comparison modes
- Exact match (default): two lines are duplicates only if they are byte-for-byte identical. The output line preserves the original casing and spaces.
- Case-insensitive: converts both lines to lowercase before comparing. Useful for lists of names, addresses, and identifiers that may arrive with inconsistent casing.
- Trim before compare: strips leading and trailing spaces and tabs before checking if a line was already seen. The output still shows the original content with spaces, but the duplicate criterion ignores the padding.
- Combined case-insensitive and trim: the most permissive mode, which treats variants with extra spaces and different casing as the same line.
Detalle técnico
Casos de uso comunes
- Listas de dependencias: los archivos requirements.txt, package.json o pom.xml que crecieron con el tiempo acumulan con frecuencia entradas duplicadas procedentes de fusiones y copias manuales.
- Imports y directivas de código: consolidar archivos de TypeScript, Python o C# de múltiples orígenes suele generar imports repetidos que compilan bien pero ensucian el código.
- Listas de direcciones y contactos: listas de correo electrónico, teléfonos o identificadores exportadas de distintos sistemas llegan llenas de duplicados con variaciones sutiles de capitalización.
- Logs de servidor: al concatenar registros de varios períodos para análisis, las líneas idénticas de advertencia o error se repiten cientos de veces y ocultan los eventos únicos.
- Archivos de configuración: las opciones de configuración duplicadas pueden causar comportamientos inesperados según qué ocurrencia utilice el parser.
Modos de comparación
- Coincidencia exacta (predeterminado): dos líneas son duplicadas solo si son idénticas byte a byte. La línea de salida conserva la capitalización y los espacios originales.
- Sin distinción entre mayúsculas y minúsculas: convierte ambas líneas a minúsculas antes de comparar. Útil para listas de nombres, direcciones e identificadores que pueden llegar con capitalización inconsistente.
- Trim antes de comparar: elimina los espacios y tabulaciones del principio y el final antes de comprobar si la línea ya se ha visto. La salida sigue mostrando el contenido original con espacios, pero el criterio de duplicado ignora el relleno.
- Combinación de sin distinción y trim: el modo más permisivo, que trata como la misma línea las variantes con espacios adicionales y capitalización diferente.
Guia da ferramenta Tool guide Guía de la herramienta
-
O que é o objeto tratado Texto multilinha (listas, logs, exports), onde cada linha é uma unidade.
-
O que a ferramenta faz Mantém só a primeira ocorrência de cada linha (com opção de ignorar espaços nas pontas na comparação).
-
Por que usar Limpar listas de e-mails, IDs ou URLs copiados de várias fontes, preparar dados únicos para importação.
-
What you are working with Multi-line text (lists, logs, exports) where each line is one unit.
-
What the tool does Keeps only the first occurrence of each line (optional trim before comparing).
-
Why use it Clean email/ID/URL lists pasted from many sources and prepare unique rows for import.
-
Con qué trabajas Texto multilínea (listas, logs, exportaciones) donde cada línea es una unidad.
-
Qué hace la herramienta Conserva solo la primera aparición de cada línea (opcionalmente recorta antes de comparar).
-
Por qué usarla Limpiar listas de correos/IDs/URLs pegadas de muchas fuentes y preparar filas únicas para importar.
Exemplo de Código Code Snippets Fragmentos de Código
function dedupeLines(text, { caseSensitive = true, trim = false } = {}) {
const seen = new Set();
return text
.split('\n')
.filter(line => {
let key = trim ? line.trim() : line;
if (!caseSensitive) key = key.toLowerCase();
if (seen.has(key)) return false;
seen.add(key);
return true;
})
.join('\n');
}
def dedupe_lines(text, case_sensitive=True, trim=False):
seen = set()
result = []
for line in text.splitlines():
key = line.strip() if trim else line
if not case_sensitive:
key = key.lower()
if key not in seen:
seen.add(key)
result.append(line)
return '\n'.join(result)
function dedupeLines(text, { caseSensitive = true, trim = false } = {}) {
const seen = new Set();
return text
.split('\n')
.filter(line => {
let key = trim ? line.trim() : line;
if (!caseSensitive) key = key.toLowerCase();
if (seen.has(key)) return false;
seen.add(key);
return true;
})
.join('\n');
}
def dedupe_lines(text, case_sensitive=True, trim=False):
seen = set()
result = []
for line in text.splitlines():
key = line.strip() if trim else line
if not case_sensitive:
key = key.lower()
if key not in seen:
seen.add(key)
result.append(line)
return '\n'.join(result)
function dedupeLines(text, { caseSensitive = true, trim = false } = {}) {
const seen = new Set();
return text
.split('\n')
.filter(line => {
let key = trim ? line.trim() : line;
if (!caseSensitive) key = key.toLowerCase();
if (seen.has(key)) return false;
seen.add(key);
return true;
})
.join('\n');
}
def dedupe_lines(text, case_sensitive=True, trim=False):
seen = set()
result = []
for line in text.splitlines():
key = line.strip() if trim else line
if not case_sensitive:
key = key.lower()
if key not in seen:
seen.add(key)
result.append(line)
return '\n'.join(result)
Antes Before Antes
a
b
a
b
c → a
b
c
Perguntas frequentes FAQ Preguntas frecuentes
Para que serve esta ferramenta?
What is this tool for?
¿Para qué sirve esta herramienta?
Ela roda 100% no seu navegador: útil para validar, formatar ou converter dados no dia a dia de desenvolvimento.
It runs fully in your browser: useful to validate, format, or convert data in everyday development.
Funciona por completo en tu navegador: sirve para validar, formatear o convertir datos en el día a día.
Meus dados são enviados a algum servidor?
Are my inputs sent to a server?
¿Se envían mis datos a algún servidor?
O processamento é feito localmente via JavaScript. Não armazenamos o conteúdo que você cola nas caixas de texto.
Processing happens locally with JavaScript. We do not store what you paste into the text areas.
El procesamiento es local con JavaScript. No almacenamos lo que pegas en los campos de texto.
Posso usar em produção ou para dados reais?
Can I use this for real production data?
¿Puedo usarlo con datos reales en producción?
Use por sua conta e risco. Para segredos (senhas, tokens), prefira ambientes controlados e políticas da sua empresa. E lembre sempre de revisar os conteúdos gerados. Nunca confie cegamente nas coisas que vê na internet.
Use at your own risk. For secrets (passwords, tokens), prefer controlled environments and your company policies. And always review the generated contents. Never trust blindly things you see on the internet.
Úsalo bajo tu responsabilidad. Para secretos (contraseñas, tokens), prefiere entornos controlados y políticas internas. Recuerda de revisar los contenidos generados. Nunca confies ciegamente en cosas que ves en internet.