我正在使用slu for elixir,我的想法是:我有一个字符串,[a-zA-Z0-9]用连字符分隔.喜欢:
string = "another-long-string-to-be-truncated-and-much-text-here"
Run Code Online (Sandbox Code Playgroud)
我想确保最大字符串长度等于30,但我也希望确保在达到最大长度时单词不会减半.所以前30个符号string是,another-long-string-to-be-trun但我希望有完全删除的another-long-string-to-be单词truncated.我怎样才能做到这一点?
首先,如果您根本不关心性能,则可以将所有工作传递给正则表达式:
~r/\A(.{0,30})(?:-|\Z)/
我认为这将是最短的解决方案,但效率不高:
iex(28)> string
"another-long-string-to-be-truncated-and-much-text-here"
iex(29)> string2
"another-long-string-to-be-cool-about-that"
iex(30)> Regex.run(~r/\A(.{0,30})(?:-|\Z)/, string) |> List.last()
"another-long-string-to-be"
iex(31)> Regex.run(~r/\A(.{0,30})(?:-|\Z)/, string2) |> List.last()
"another-long-string-to-be-cool"
Run Code Online (Sandbox Code Playgroud)
但是,如果您确实关心性能和内存,那么我建议这样做:
defmodule CoolSlugHelper do
def slug(input, length \\ 30) do
length_minus_1 = length - 1
case input do
# if the substring ends with "-"
# i. e. "abc-def-ghi", 8 or "abc-def-", 8 -> "abc-def"
<<result::binary-size(length_minus_1), "-", _::binary>> -> result
# if the next char after the substring is "-"
# i. e. "abc-def-ghi", 7 or "abc-def-", 7 -> "abc-def"
<<result::binary-size(length), "-", _::binary>> -> result
# if it is the exact string. i. e. "abc-def", 7 -> "abc-def"
<<_::binary-size(length)>> -> input
# return an empty string if we reached the beginnig of the string
_ when length <= 1 -> ""
# otherwise look into shorter substring
_ -> slug(input, length_minus_1)
end
end
end
Run Code Online (Sandbox Code Playgroud)
它不会按字符收集结果字符串。而是从所需长度到1的范围内寻找正确的子字符串。这就是它在内存和速度方面变得有效的方式。
我们需要此length_minus_1变量,因为我们不能在binary-size二进制模式匹配中使用表达式。
这是截至2018年12月22日所有拟议解决方案的基准:
(简单的~r/\A(.{0,30})(?:-|\Z)/正则表达式就是上面的正则表达式)
Name ips average deviation median 99th %
CoolSlugHelper 352.14 K 2.84 ?s ±1184.93% 2 ?s 8 ?s
SlugHelper 70.98 K 14.09 ?s ±170.20% 10 ?s 87 ?s
Simple Regex 33.14 K 30.17 ?s ±942.90% 21 ?s 126 ?s
Truncation 11.56 K 86.51 ?s ±84.81% 62 ?s 299 ?s
Comparison:
CoolSlugHelper 352.14 K
SlugHelper 70.98 K - 4.96x slower
Simple Regex 33.14 K - 10.63x slower
Truncation 11.56 K - 30.46x slower
Memory usage statistics:
Name Memory usage
CoolSlugHelper 2.30 KB
SlugHelper 12.94 KB - 5.61x memory usage
Simple Regex 20.16 KB - 8.75x memory usage
Truncation 35.36 KB - 15.34x memory usage
Run Code Online (Sandbox Code Playgroud)
UPD 12/2018 Yuri Golobokov在这里发布了更好的解决方案,我建议在下面使用它。
最简单的方法是:
"another-long-string-to-be-truncated-and-much-text-here"
|> String.slice(0..29)
|> String.replace(~r{-[^-]*$}, "")
#? "another-long-string-to-be"
Run Code Online (Sandbox Code Playgroud)
有一个小故障:如果连字符恰好在第31位,则最后一项将被删除。为了避免这种情况,可以明确检查上述情况:
str = "another-long-string-to-be-truncated-and-much-text-here"
case str |> String.at(30) do
"-" -> str |> String.slice(0..29)
_ -> str |> String.slice(0..29) |> String.replace(~r{-[^-]*$}, "")
end
#? "another-long-string-to-be"
Run Code Online (Sandbox Code Playgroud)
要么:
orig = "another-long-string-to-be-cool-cated-and-much-text-here"
str = orig |> String.slice(0..29)
unless String.at(orig, 30) == "-", do: str = str |> String.replace(~r{-[^-]*$}, "")
str
#? "another-long-string-to-be-cool"
Run Code Online (Sandbox Code Playgroud)