Last active
January 30, 2025 14:53
-
-
Save meagar/fb1d30163f0628eede769f2298f51f15 to your computer and use it in GitHub Desktop.
Join/Split with arbitrary single-char dlimiter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def join(strings, delimiter) | |
raise ArgumentError, "Invalid delimiter \"\\\"" if delimiter == "\\" | |
strings.map do |s| | |
s.gsub(/(\\|#{Regexp.escape(delimiter)})/, '\\\\\1') | |
end.join(delimiter) | |
end | |
def split(string, delimiter) | |
raise ArgumentError, "Invalid delimiter \"\\\"" if delimiter == "\\" | |
strings = [] | |
token = nil | |
literal = false | |
string.chars.each do |char| | |
token ||= "" | |
if literal | |
token += char | |
literal = false | |
next | |
end | |
case char | |
when "\\" | |
literal = true | |
when delimiter | |
strings << token | |
token = "" | |
else | |
token += char | |
end | |
end | |
raise ArgumentError, "dangling escape" if literal | |
strings << token unless token.nil? | |
strings | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative './delim' | |
# { delimiter => { string => array , ... }, ... } | |
# for each string/array pair S/A: | |
# - join(A) == S | |
# - split(S) == A | |
test_cases = { | |
":" => { | |
"" => [], | |
"foo" => ["foo"], | |
":" => ["", ""], | |
"foo:bar" => ["foo", "bar"], | |
'foo\:bar' => ["foo:bar"], | |
"foo:" => ["foo", ""], | |
"foo:bar:" => ["foo", "bar", ""], | |
':foo\::\:bar:\:::' => ["", "foo:", ":bar", ":", "", ""], | |
"\\\\:foo" => ["\\", "foo"], | |
"\\\\\\:foo" => ["\\:foo"], | |
"foo\\\\\\:\\\\bar" => ["foo\\:\\bar"] | |
}, | |
# Regex character | |
"|" => { | |
"" => [], | |
"foo" => ["foo"], | |
"|" => ["", ""], | |
"foo|bar" => ["foo", "bar"], | |
'foo\|bar' => ["foo|bar"], | |
"foo|" => ["foo", ""], | |
"foo|bar|" => ["foo", "bar", ""], | |
'|foo\||\|bar|\|||' => ["", "foo|", "|bar", "|", "", ""], | |
"\\\\|foo" => ["\\", "foo"], | |
"\\\\\\|foo" => ["\\|foo"], | |
"foo\\\\\\|\\\\bar" => ["foo\\|\\bar"] | |
}, | |
" " => { | |
"" => [], | |
"foo" => ["foo"], | |
" " => ["", "", "", ""], | |
' \ ' => ["", " ", ""], | |
"this is a test" => ["this", "is", "a", "test"], | |
%q[\ this\ is a\ test\ ] => [" this is", "a test "] | |
}, | |
"\n" => { | |
"" => [], | |
"\n" => ["", ""], | |
"foo\nbar" => ["foo", "bar"], | |
"foo\\\nbar" => ["foo\nbar"], | |
"\nfoo\\\nbar\n" => ["", "foo\nbar", ""] | |
} | |
} | |
test_cases.each do |delimiter, cases| | |
cases.each do |str, arr| | |
got = split(str, delimiter) | |
if got != arr | |
puts "split(#{str.inspect}, #{delimiter.inspect}): Got #{got.inspect}, want #{arr.inspect}" | |
end | |
end | |
cases.each do |str, arr| | |
got = join(arr, delimiter) | |
if got != str | |
puts "join(#{arr.inspect}, #{delimiter.inspect}): Got #{got.inspect}, want #{str.inspect}" | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment