Skip to content

Instantly share code, notes, and snippets.

@meagar
Last active August 16, 2024 15:55
Show Gist options
  • Save meagar/fb1d30163f0628eede769f2298f51f15 to your computer and use it in GitHub Desktop.
Save meagar/fb1d30163f0628eede769f2298f51f15 to your computer and use it in GitHub Desktop.
Join/Split with arbitrary single-char dlimiter
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
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