Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -1,9 +1,24 @@
|
|||
It is often necessary to split a string into pieces based on several different (potentially multi-character) separator strings, while still retaining the information about which separators were present in the input. This is particularly useful when doing small parsing tasks. The task is to write code to demonstrate this.
|
||||
It is often necessary to split a string into pieces
|
||||
based on several different (potentially multi-character) separator strings,
|
||||
while still retaining the information about which separators were present in the input.
|
||||
|
||||
The function (or procedure or method, as appropriate) should take an input string and an ordered collection of separators. The order of the separators is significant: The delimiter order represents priority in matching, with the first defined delimiter having the highest priority. In cases where there would be an ambiguity as to which separator to use at a particular point (e.g., because one separator is a prefix of another) the separator with the highest priority should be used. Delimiters can be reused and the output from the function should be an ordered sequence of substrings.
|
||||
This is particularly useful when doing small parsing tasks. <br>
|
||||
The task is to write code to demonstrate this.
|
||||
|
||||
The function (or procedure or method, as appropriate) should
|
||||
take an input string and an ordered collection of separators.
|
||||
|
||||
The order of the separators is significant: <br>
|
||||
The delimiter order represents priority in matching, with the first defined delimiter having the highest priority.
|
||||
In cases where there would be an ambiguity as to
|
||||
which separator to use at a particular point
|
||||
(e.g., because one separator is a prefix of another)
|
||||
the separator with the highest priority should be used.
|
||||
Delimiters can be reused and the output from the function should be an ordered sequence of substrings.
|
||||
|
||||
Test your code using the input string “<code>a!===b=!=c</code>” and the separators “<code>==</code>”, “<code>!=</code>” and “<code>=</code>”.
|
||||
|
||||
For these inputs the string should be parsed as <code>"a" (!=) "" (==) "b" (=) "" (!=) "c"</code>, where matched delimiters are shown in parentheses, and separated strings are quoted, so our resulting output is <code>"a", empty string, "b", empty string, "c"</code>. Note that the quotation marks are shown for clarity and do not form part of the output.
|
||||
For these inputs the string should be parsed as <code>"a" (!=) "" (==) "b" (=) "" (!=) "c"</code>, where matched delimiters are shown in parentheses, and separated strings are quoted, so our resulting output is <code>"a", empty string, "b", empty string, "c"</code>.
|
||||
Note that the quotation marks are shown for clarity and do not form part of the output.
|
||||
|
||||
'''Extra Credit:''' provide information that indicates which separator was matched at each separation point and where in the input string that separator was matched.
|
||||
|
|
|
|||
3
Task/Multisplit/00META.yaml
Normal file
3
Task/Multisplit/00META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
category:
|
||||
- String manipulation
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
import std.stdio, std.array, std.algorithm;
|
||||
|
||||
string[] multiSplit(in string s, in string[] divisors)
|
||||
pure /*nothrow*/ {
|
||||
string[] multiSplit(in string s, in string[] divisors) pure nothrow {
|
||||
string[] result;
|
||||
auto rest = s.idup; // Not nothrow.
|
||||
auto rest = s.idup;
|
||||
|
||||
while (true) {
|
||||
bool done = true;
|
||||
string delim;
|
||||
{
|
||||
string best;
|
||||
foreach (div; divisors) {
|
||||
foreach (const div; divisors) {
|
||||
const maybe = rest.find(div);
|
||||
if (maybe.length > best.length) {
|
||||
best = maybe;
|
||||
|
|
|
|||
27
Task/Multisplit/Haskell/multisplit.hs
Normal file
27
Task/Multisplit/Haskell/multisplit.hs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import Data.List as L
|
||||
import Data.Maybe
|
||||
|
||||
trysplit :: Eq a => [a] -> [[a]] -> Maybe ([a], [a])
|
||||
trysplit s delims =
|
||||
case filter (`L.isPrefixOf` s) delims of
|
||||
[] -> Nothing
|
||||
(d:_) -> Just (d, fromJust $ L.stripPrefix d s)
|
||||
|
||||
multisplit :: (Eq a, Num n) => [a] -> [[a]] -> [([a], [a], n)]
|
||||
multisplit list delims =
|
||||
let ms [] acc pos = [(acc, [], pos)]
|
||||
ms l@(s:sx) acc pos =
|
||||
case trysplit l delims of
|
||||
Nothing -> ms sx (s:acc) (pos + 1)
|
||||
Just (d, sxx) -> (acc, d, pos) : ms sxx [] (pos + L.genericLength d)
|
||||
in ms list [] 0
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
let test = "a!===b=!=c"
|
||||
delims = ["==", "!=", "="]
|
||||
parsed = multisplit test delims
|
||||
putStrLn "split string:"
|
||||
putStrLn $ L.intercalate "," $ map (\(a, _, _) -> a) parsed
|
||||
putStrLn "with [(string, delimiter, offset)]:"
|
||||
print parsed
|
||||
33
Task/Multisplit/Java/multisplit.java
Normal file
33
Task/Multisplit/Java/multisplit.java
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import java.util.*;
|
||||
|
||||
public class MultiSplit {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Regex split:");
|
||||
System.out.println(Arrays.toString("a!===b=!=c".split("==|!=|=")));
|
||||
|
||||
System.out.println("\nManual split:");
|
||||
for (String s : multiSplit("a!===b=!=c", new String[]{"==", "!=", "="}))
|
||||
System.out.printf("\"%s\" ", s);
|
||||
}
|
||||
|
||||
static List<String> multiSplit(String txt, String[] separators) {
|
||||
List<String> result = new ArrayList<>();
|
||||
int txtLen = txt.length(), from = 0;
|
||||
|
||||
for (int to = 0; to < txtLen; to++) {
|
||||
for (String sep : separators) {
|
||||
int sepLen = sep.length();
|
||||
if (txt.regionMatches(to, sep, 0, sepLen)) {
|
||||
result.add(txt.substring(from, to));
|
||||
from = to + sepLen;
|
||||
to = from - 1; // compensate for the increment
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (from < txtLen)
|
||||
result.add(txt.substring(from));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +1,26 @@
|
|||
/*REXX program to split a string based on different separator strings. */
|
||||
/*REXX program splits a string based on different separator strings.*/
|
||||
parse arg ? /*get string from command line. */
|
||||
if ?=='' then ? = 'a!===b=!=c' /*None specified? Use default.*/
|
||||
if ?=='' then ? = "a!===b=!=c" /*None specified? Use default.*/
|
||||
say 'old string='? /*echo the old string to screen. */
|
||||
zz = '0'x /*null char, can be most anything*/
|
||||
seps = '== != =' /*a list of seperaters to be used*/
|
||||
|
||||
seps = '== != =' /*a list of seperators to be used*/
|
||||
/* [↓] process tokens in SEPS.*/
|
||||
do j=1 for words(seps) /*parse string with all the seps.*/
|
||||
sep=word(seps,j) /*pick a separater to use now. */
|
||||
|
||||
sep=word(seps,j) /*pick a separator to use now. */
|
||||
/* [↓] process chars in the sep*/
|
||||
do k=1 for length(sep) /*parse for various sep versions.*/
|
||||
sep=strip(insert(zz,sep,k),,zz) /*allow imbedded "nulls" in sep. */
|
||||
?=changestr(sep,?,zz) /* ··· but not trailing "nulls". */
|
||||
|
||||
/* [↓] process strings in input*/
|
||||
do until ?==??; ??=? /*keep changing until no more chg*/
|
||||
?=changestr(zz || zz, ?, zz) /*reduce replicated "nulls". */
|
||||
end /*until···*/
|
||||
|
||||
/* [↓] use BIF or external prog.*/
|
||||
sep=changestr(zz, sep, '') /*remove true nulls from the sep.*/
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
|
||||
showNull = ' {} ' /*one last change, allow the ... */
|
||||
?=changestr(zz,?,showNull) /*showing of "null" characters. */
|
||||
say 'new string='? /*now, show and tell time. */
|
||||
showNull = ' {} ' /*one more thing, display the ···*/
|
||||
?=changestr(zz,?,showNull) /* ··· showing of "null" chars. */
|
||||
say 'new string='? /*now, display the new string. */
|
||||
/*stick a fork in it, we're done.*/
|
||||
|
|
|
|||
|
|
@ -2,13 +2,7 @@ text = 'a!===b=!=c'
|
|||
separators = ['==', '!=', '=']
|
||||
|
||||
def multisplit_simple(text, separators)
|
||||
sep_regex = Regexp.new(separators.collect {|sep| Regexp.escape(sep)}.join('|'))
|
||||
text.split(sep_regex)
|
||||
text.split(Regexp.union(separators))
|
||||
end
|
||||
|
||||
p multisplit_simple(text, separators)
|
||||
["a", "", "b", "", "c"]
|
||||
=> nil
|
||||
p multisplit_simple(text, ['=', '!=', '=='])
|
||||
["a", "", "", "b", "", "c"]
|
||||
=> nil
|
||||
p multisplit_simple(text, separators) # => ["a", "", "b", "", "c"]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
def multisplit(text, separators)
|
||||
sep_regex = Regexp.new(separators.collect {|sep| Regexp.escape(sep)}.join('|'))
|
||||
sep_regex = Regexp.union(separators)
|
||||
separator_info = []
|
||||
pieces = []
|
||||
i = prev = 0
|
||||
|
|
|
|||
15
Task/Multisplit/Scheme/multisplit.ss
Normal file
15
Task/Multisplit/Scheme/multisplit.ss
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
(use srfi-13)
|
||||
(use srfi-42)
|
||||
|
||||
(define (shatter separators the-string)
|
||||
(let loop ((str the-string) (tmp ""))
|
||||
(if (string=? "" str)
|
||||
(list tmp)
|
||||
(if-let1 sep (find (^s (string-prefix? s str)) separators)
|
||||
(cons* tmp sep
|
||||
(loop (string-drop str (string-length sep)) ""))
|
||||
(loop (string-drop str 1) (string-append tmp (string-take str 1)))))))
|
||||
|
||||
(define (glean shards)
|
||||
(list-ec (: x (index i) shards)
|
||||
(if (even? i)) x))
|
||||
29
Task/Multisplit/UNIX-Shell/multisplit.sh
Normal file
29
Task/Multisplit/UNIX-Shell/multisplit.sh
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
multisplit() {
|
||||
local str=$1
|
||||
shift
|
||||
local regex=$( IFS='|'; echo "$*" )
|
||||
local sep
|
||||
while [[ $str =~ $regex ]]; do
|
||||
sep=${BASH_REMATCH[0]}
|
||||
words+=( "${str%%${sep}*}" )
|
||||
seps+=( "$sep" )
|
||||
str=${str#*$sep}
|
||||
done
|
||||
words+=( "$str" )
|
||||
}
|
||||
|
||||
words=() seps=()
|
||||
|
||||
original="a!===b=!=c"
|
||||
recreated=""
|
||||
|
||||
multisplit "$original" "==" "!=" "="
|
||||
|
||||
for ((i=0; i<${#words[@]}; i++)); do
|
||||
printf 'w:"%s"\ts:"%s"\n' "${words[i]}" "${seps[i]}"
|
||||
recreated+="${words[i]}${seps[i]}"
|
||||
done
|
||||
|
||||
if [[ $original == $recreated ]]; then
|
||||
echo "successfully able to recreate original string"
|
||||
fi
|
||||
Loading…
Add table
Add a link
Reference in a new issue