Multisplit: Difference between revisions
Content deleted Content added
→{{header|Haskell}}: Additional example (multisplit by fold) |
→{{header|JavaScript}}: ES6 (without importing Underscore, and generalising to allow for any set of delimiters) |
||
Line 826: | Line 826: | ||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
===ES5=== |
|||
Based on Ruby example. |
Based on Ruby example. |
||
{{libheader|Underscore.js}} |
{{libheader|Underscore.js}} |
||
Line 836: | Line 837: | ||
return string.split(sep_regex); |
return string.split(sep_regex); |
||
}</lang> |
}</lang> |
||
===ES6=== |
|||
Without importing an external library, and generalizing to allow for any set of delimiters (avoiding the need for a hand-crafted regex): |
|||
{{Trans|Haskell}} (Multisplit by fold example) |
|||
<lang javascript>(() => { |
|||
/// Delimiter list -> String -> list of parts, delimiters, offsets |
|||
// multiSplit :: [String] -> String -> |
|||
// [{part::String, delim::String, offset::Int}] |
|||
const multiSplit = (ds, s) => { |
|||
const |
|||
dcs = map(chars, ds), |
|||
xs = chars(s), |
|||
dct = foldl( |
|||
(a, c, i, s) => { |
|||
const |
|||
inDelim = a.offset > i, |
|||
mb = inDelim ? ( |
|||
nothing('') |
|||
) : find(d => isPrefixOf(d, drop(i, xs)), dcs); |
|||
return mb.nothing ? { |
|||
tokens: a.tokens.concat(inDelim ? ( |
|||
[] |
|||
) : [c]), |
|||
parts: a.parts, |
|||
offset: a.offset |
|||
} : { |
|||
tokens: [], |
|||
parts: append(a.parts, [{ |
|||
part: intercalate('', a.tokens), |
|||
delim: intercalate('', mb.just), |
|||
offset: i |
|||
}]), |
|||
offset: i + length(mb.just) |
|||
}; |
|||
}, { |
|||
tokens: [], |
|||
parts: [], |
|||
offset: 0 |
|||
}, xs |
|||
); |
|||
return append(dct.parts, [{ |
|||
part: intercalate('', dct.tokens), |
|||
delim: "", |
|||
offset: length(s) |
|||
}]); |
|||
}; |
|||
// GENERIC FUNCTIONS ----------------------------------------------------- |
|||
// append (++) :: [a] -> [a] -> [a] |
|||
const append = (xs, ys) => xs.concat(ys); |
|||
// chars :: String -> [Char] |
|||
const chars = s => s.split(''); |
|||
// drop :: Int -> [a] -> [a] |
|||
// drop :: Int -> String -> String |
|||
const drop = (n, xs) => xs.slice(n); |
|||
// find :: (a -> Bool) -> [a] -> Maybe a |
|||
const find = (p, xs) => { |
|||
for (var i = 0, lng = xs.length; i < lng; i++) { |
|||
var x = xs[i]; |
|||
if (p(x)) return just(x); |
|||
} |
|||
return nothing('Not found'); |
|||
}; |
|||
// foldl :: (a -> b -> a) -> a -> [b] -> a |
|||
const foldl = (f, a, xs) => xs.reduce(f, a); |
|||
// intercalate :: String -> [String] -> String |
|||
const intercalate = (s, xs) => xs.join(s); |
|||
// isPrefixOf takes two lists or strings and returns |
|||
// true iff the first is a prefix of the second. |
|||
// isPrefixOf :: [a] -> [a] -> Bool |
|||
// isPrefixOf :: String -> String -> Bool |
|||
const isPrefixOf = (xs, ys) => { |
|||
const pfx = (xs, ys) => xs.length ? ( |
|||
ys.length ? xs[0] === ys[0] && pfx( |
|||
xs.slice(1), ys.slice(1) |
|||
) : false |
|||
) : true; |
|||
return typeof xs !== 'string' ? pfx(xs, ys) : ys.startsWith(xs); |
|||
}; |
|||
// just :: a -> Just a |
|||
const just = x => ({ |
|||
nothing: false, |
|||
just: x |
|||
}); |
|||
// length :: [a] -> Int |
|||
const length = xs => xs.length; |
|||
// map :: (a -> b) -> [a] -> [b] |
|||
const map = (f, xs) => xs.map(f); |
|||
// nothing :: () -> Nothing |
|||
const nothing = (optionalMsg) => ({ |
|||
nothing: true, |
|||
msg: optionalMsg |
|||
}); |
|||
// show :: Int -> a -> Indented String |
|||
// show :: a -> String |
|||
const show = (...x) => |
|||
JSON.stringify.apply( |
|||
null, x.length > 1 ? [x[1], null, x[0]] : x |
|||
); |
|||
// TEST ------------------------------------------------------------------ |
|||
const |
|||
strTest = 'a!===b=!=c', |
|||
delims = ['==', '!=', '=']; |
|||
return show(2, |
|||
multiSplit(delims, strTest) |
|||
); |
|||
})();</lang> |
|||
{{Out}} |
|||
<pre>[ |
|||
{ |
|||
"part": "a", |
|||
"delim": "!=", |
|||
"offset": 1 |
|||
}, |
|||
{ |
|||
"part": "", |
|||
"delim": "==", |
|||
"offset": 3 |
|||
}, |
|||
{ |
|||
"part": "b", |
|||
"delim": "=", |
|||
"offset": 6 |
|||
}, |
|||
{ |
|||
"part": "", |
|||
"delim": "!=", |
|||
"offset": 7 |
|||
}, |
|||
{ |
|||
"part": "c", |
|||
"delim": "", |
|||
"offset": 10 |
|||
} |
|||
]</pre> |
|||
=={{header|jq}}== |
=={{header|jq}}== |
||
{{Works with|jq|1.4}} |
{{Works with|jq|1.4}} |