locutus
Version:
Locutus other languages' standard libraries to JavaScript for fun and educational purposes
49 lines (48 loc) • 1.75 kB
JavaScript
function normalizeMapEntries(mappings) {
if (Array.isArray(mappings)) {
if (mappings.every((entry) => Array.isArray(entry) && entry.length === 2)) {
return mappings.map((entry) => [String(entry[0]), String(entry[1])]);
}
const out = [];
for (let i = 0; i + 1 < mappings.length; i += 2) {
out.push([String(mappings[i]), String(mappings[i + 1])]);
}
return out;
}
return Object.entries(mappings).map(([key, value]) => [String(key), String(value)]);
}
export function map(mappings, str) {
// discuss at: https://locutus.io/tcl/map/
// parity verified: Tcl 8.6
// original by: Kevin van Zonneveld (https://kvz.io)
// note 1: Applies key/value replacements in left-to-right single-pass order like Tcl string map.
// example 1: map(['abc', 'X', 'a', 'Y'], 'abc abca')
// returns 1: 'X XY'
// example 2: map(['cat', 'dog', ' ', '_'], 'cat cat')
// returns 2: 'dog_dog'
// example 3: map(['ab', 'X', 'a', 'Y'], 'ababa')
// returns 3: 'XXY'
const source = String(str);
const entries = normalizeMapEntries(mappings).filter(([key]) => key.length > 0);
if (entries.length === 0) {
return source;
}
let out = '';
let cursor = 0;
while (cursor < source.length) {
let matched = false;
for (const [key, value] of entries) {
if (source.startsWith(key, cursor)) {
out += value;
cursor += key.length;
matched = true;
break;
}
}
if (!matched) {
out += source[cursor];
cursor += 1;
}
}
return out;
}