| Bytes | Lang | Time | Link |
|---|---|---|---|
| 051 | Desmos | 250924T023302Z | DesmosEn |
| 032 | Arturo | 250918T165212Z | chunes |
| 042 | Factor | 250917T185842Z | chunes |
| 039 | Python | 250915T151108Z | Albert.L |
| 003 | Jelly | 250916T231224Z | Jonathan |
| 012 | Pip p | 250916T200342Z | DLosc |
| 046 | Haskell | 250916T110012Z | RubenVer |
| 028 | x86_64 machine code | 250916T140910Z | Ifier |
| 022 | R | 250915T152502Z | Giuseppe |
| 044 | Haskell | 250916T111736Z | xnor |
| 110 | Haskell | 250916T061536Z | Dannyu N |
| 028 | JavaScript ES12 | 250915T131823Z | Arnauld |
| 003 | MATL | 250916T042733Z | Luis Men |
| 004 | 05AB1E | 250915T235834Z | Lucenapo |
| 053 | Maple | 250915T234340Z | dharr |
| 037 | Google Sheets | 250915T204031Z | doubleun |
| 013 | Charcoal | 250915T145049Z | Neil |
| 027 | APLNARS | 250915T144719Z | Rosario |
| 031 | Ruby | 250915T142830Z | G B |
| 004 | Vyxal 3 | 250915T135258Z | Themooni |
| 002 | TinyAPL | 250915T135049Z | RubenVer |
| 003 | Uiua | 250915T131742Z | lyxal |
Desmos, 51 Bytes
f(a)=b[a[i]=a.unique][1]fori=b
b=[1...a.count][a=a]
This works by looping over the array a, and for each element, the new value is the index of that item in the "unique" array, which is the array of unique items in the array a, in order of when they appear.
b= // Initialise b
[1...a.count] // Make a list of consecutive numbers up to the length of the "a" array
[a=a] // Filter array by if that element of a = itself (this makes sure that if a is an empty array, b is empty as well, instead of [1,0])
f(a)= // Declare main function
fori=b // Loop for every element in b
b[ ][1] // Loop over b and find the first element in b that satisfies the following condition
a[i]=a.unique // The item being checked by the outer loop is equivalent to the b'th element of the "unique items" list
Factor, 42 bytes
[ dup members zip-index substitute 1 v+n ]
Factor + math.extras, 28 bytes
[ unique-indices nip 1 v+n ]
Python, 39 bytes
lambda L:map([*dict(zip(L,L))].index,L)
Output is zero-based.
If you must have one-based, @Lucenaposition has a 2 byte fix:
Python, 41 bytes
lambda L:map([L,*dict(zip(L,L))].index,L)
Notes
We use a dict where a set would appear more logical, because dicts are guaranteed to keep key creation order.
Jelly, 3 bytes
QiⱮ
A monadic Link that accepts a list of positive integers and yields its lexicographically minimal relabeling.
How?
QiⱮ - Link: list of positive integers, L
Q - deduplicate {L}
Ɱ - map with:
i - first 1-index of {current element of L} in {deduplicated L}
Pip -p, 12 bytes
U:(UQg)@?_Mg
Explanation
U:(UQg)@?_Mg
Mg Map this function to the list of command-line arguments:
@? Find the first (0-based) index of
_ The function argument
(UQg) In the uniquified list of command-line arguments
U: Increment the result list to make it 1-based
Haskell, 46 bytes
import Data.List
flip elemIndex.(:)0.nub>>=map
Returns a [Maybe Int] where all the maybes are (trivially) Justs, which is allowed.
Thanks @xnor and @Wheat Wizard for -14
Explanation: index of each element of the input in the unique elements of the input prefixed with 0 (which is always extraneous and therefore amounts to adding 1 to the indices)
x86_64 machine code, 28 bytes
0: 53 push rbx
1: e3 17 jrcxz 1a <end>
3: 52 push rdx
4: 5b pop rbx
5: 31 c0 xor eax,eax
0000000000000007 <load>:
7: ac lods al,BYTE PTR ds:[rsi]
8: 0f b6 d0 movzx edx,al
b: d7 xlat BYTE PTR ds:[rbx]
c: 84 c0 test al,al
e: 75 07 jne 17 <store>
0000000000000010 <mklabel>:
10: fe c4 inc ah
12: 88 24 13 mov BYTE PTR [rbx+rdx*1],ah
15: 88 e0 mov al,ah
0000000000000017 <store>:
17: aa stos BYTE PTR es:[rdi],al
18: e2 ed loop 7 <load>
000000000000001a <end>:
1a: 5b pop rbx
1b: c3 ret
Uses sysv calling convention, takes a C-style function interface of:
void relabel(unsigned char* out, unsigned char* original, unsigned char* table, unsigned long long count)
where out is an appropriately sized output buffer and table is a zero-initialised array of bytes equal in size to at least the number of unique symbols in the input + 1.
It simply goes through the input, looks up the translation for the character in a lookup table, generates a lookup table entry is the translation is 0 (uninitialised), and then stores the translated character in the output. I'm treating output bytes at 8-bit binary numbers instead of characters.
R, 22 bytes
\(a)match(a,unique(a))
Self-applied match() very nearly has this functionality.
Thanks to jared_mamrot and SamR in the comments for prompting discussion around factor(): At first glance, since factors are stored as integers, it seems that factor should be a complete answer at 6 bytes, but unfortunately by default the levels are computed as sort(unique(x)), where the sort screws up the lexicographically first relabelling, so we end up with \(a)factor(a,unique(a)), which is 23 bytes, and technically prints out the original array.
Haskell, 44 bytes
map=<<g
g(h:t)n|h==n=1|1>0=1+g[x|x<-t,x/=h]n
Look ma, no imports!
The main function is pointfree for f l=g l<$>l.
The helper g takes a list and a value n, and counts the distinct elements up to the first appearance of n. With nub, this could be 1+length(nub$fst$span(/=n)l), but nub requires an import. Instead, g recurses, adding 1 for each new element until it reaches the target value n (with base value 1 for 1-indexing), and filtering out repeats of the current element h in its recursive call.
Haskell, 110 bytes
i!(x@(Left _):xs)=i:(i+1)!map(\y->if y==x then Right i else y)xs
i!(Right x:xs)=x:i!xs
_!_=[]
f x=1!map Left x
Lesson of today: Either is useful.
JavaScript (ES12), 28 bytes
a=>a.map(k=v=>a[-v]||=k=-~k)
Commented
a => // a[] = input array, re-used to store the new labels
// using negative keys
a.map(k = // k = counter, initially zero'ish
v => // for each value v in a[]:
a[-v] ||= // use a[-v] if it's already defined,
k = -~k // otherwise increment k and set a[-v] to this value
) // end of map()
MATL, 3 bytes
7#u
Try it online! Or verify test cases 1, 2, 3, 4.
The code inputs a numerical vector, and print the output with a number on each line. The empty input produces the correct output but exits with an error (allowed by default).
How it works
% Implicit input: numerical vector
#7u % Call 'unique' with its third output, and with 'stable' input flag (default)
% Implicit display
Maple, 53 bytes
s->subs((v:=ListTools:-MakeUnique(s))=~{$nops(v)},s);
The unique entries in order (v) are elementwise equated to 1,2,3,..(number in v), and used as substitution rules in s. ListTools:-MakeUnique is frustratingly verbose, but still shorter than anything I can think of that processes the list one entry as a time, such as
proc(s)q:=1;[seq(if(assigned(w[i]),w[i],(w[i]:=q++)),i=s)]end; (64 bytes)
Google Sheets, 37 bytes
=index(ifna(match(A:A,unique(A:A),)))
...not the typical use of the index(match()) pattern, using index() as array enabler only.

Charcoal, 13 bytes
I⊕Eθ⌕Φθ⁼μ⌕θλι
Try it online! Link is to verbose version of code. Explanation:
θ Input array
E Map over values
ι Current value
⌕ Find index in
θ Input array
Φ Filtered where
μ Inner index
⁼ Equals
⌕ First index of
λ Inner value in
θ Input array
⊕ Convert to 1-indexing
I Cast to string
Implicitly print
APL(NARS), 27 chars
{⍬≡w←⍵:⍬⋄↑+/k×⍳≢k←{w=⍵}¨∪⍵}
input one array, ouput one array. Make one array of binary array where are each element, multiply for according iota array of right lengh and sum. Because the output was right enclosed, get the first ↑.
Test:
f←{⍬≡w←⍵:⍬⋄↑+/k×⍳≢k←{w=⍵}¨∪⍵}
f ⍬
┌0─┐
│ 0│
└~─┘
f ,9
┌1─┐
│ 1│
└~─┘
f 2 3 2 2 4 5 4 4 2
┌9─────────────────┐
│ 1 2 1 1 3 4 3 3 1│
└~─────────────────┘
f 3 4 2 1 1 1 1 1 1
┌9─────────────────┐
│ 1 2 3 4 4 4 4 4 4│
└~─────────────────┘
Vyxal 3, 4 bytes
u¨F›
u¨F›
¨F # find each
u # unique element in the input
› # increment the index
💎
Created with the help of Luminespire.
<script type="vyxal3">
u¨F›
</script>
<script>
args=[["[]"],["[9]"],["[2,3,2,2,4,5,4,4,2]"],["[3,4,2,1,1,1,1,1,1,1]"]]
</script>
<script src="https://themoonisacheese.github.io/snippeterpreter/snippet.js" type="module"/>
TinyAPL, 2 bytes
=⑴
Explanation: classify with index origin 1.
Uiua, 3 bytes
+1⊛
Saw the challenge specs and immediately thought of classify in uiua lol.
Explained
+1⊛
⊛ # Assign a unique index to each unique item in the input
+1 # and add 1 to each index.
💎
Created with the help of Luminespire.