我正在使用slu for elixir,我的想法是:我有一个字符串,其中string = "another-long-string-to-be-truncated-and-much-text-here"
个单词用连字符分隔。像:
string
我希望确保最大字符串长度等于30,但我还要确保在达到最大长度时字数不会减半。因此another-long-string-to-be-trun
的前30个符号为another-long-string-to-be
,但我希望将truncated
与export PATH=$PATH:/usr/local/mysql/bin
字完全删除。我怎么能这样做?
答案 0 :(得分:5)
首先,如果您根本不关心性能,则可以将所有工作转发给正则表达式:
~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"
但是,如果您确实关心性能和内存,那么我建议这样做:
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
它不按字符收集结果字符串。而是从所需长度到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
答案 1 :(得分:4)
UPD 12/2018 Yuri Golobokov发布了更好的解决方案here,我建议使用它而不是以下内容。
最简单的方法是:
"another-long-string-to-be-truncated-and-much-text-here"
|> String.slice(0..29)
|> String.replace(~r{-[^-]*$}, "")
#⇒ "another-long-string-to-be"
它有一个小故障:如果连字符正好在第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"
或:
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"
答案 2 :(得分:1)
你可以递归地做..
defmodule Truncation do
def truncate_words_to(str, max) do
length = String.length(str)
words? = Regex.match?(~r{-}, str)
cond do
length <= max -> str
words? -> truncate_words_to(String.replace(str, ~r{-[^-]*$}, ""),
max)
true -> String.slice(str, 0..(max-1))
end
end
end
答案 3 :(得分:1)
由于此问题仍然受到搜索引擎的欢迎,因此,我会发布正确,快速,精妙的解决方案来完成此任务。
struct C
{
C() :second(dummy)
{
}
~C() // force a destructor
{
}
int * first = nullptr;
std::vector<int>& second;
};
答案 4 :(得分:0)
我的回答基于@mudasobwa的答案,但我决定简化它
"another-long-string-to-be-truncated-and-much-text-here"
|> String.slice(0..29)
|> String.split("-")
|> Enum.slice(0..-2)
|> Enum.join("-")
就是这样!