将字符串“恰好”截断为*个字节*

时间:2019-07-17 15:10:55

标签: elixir

说我有一个字符串,例如s = "abcdé",我想将其截断为许多 bytes ,在本例中为五(5)。但是,由于最后一个“字形”由多个字节组成,所以我想byte_truncate_nicely(s, 5) == "abcd"是正确的,因为这似乎不明智,例如使用binary_part,然后分割最终的字素。

3 个答案:

答案 0 :(得分:3)

我不知道这样的功能是否存在,但是您可以自己编写

bytes_number = 5

"abcdé"
|> String.split("") 
|> Enum.reduce_while("", 
   fn char, acc -> 
     if byte_size(acc <> char) <= bytes_number do
       {:cont, acc <> char}
     else
       {:halt, acc}
     end
   end)

答案 1 :(得分:2)

我认为没有内置方法可以执行此操作,但是您可以手动完成。

  def take_bytes(str, limit) do
    str
    |> String.graphemes()
    |> Enum.reduce({[], 0}, fn g, {acc, sum} ->
      next_size = byte_size(g)

      if sum + next_size > limit do
        {acc, sum}
      else
        {[g | acc], sum + next_size}
      end
    end)
    |> elem(0)
    |> Enum.join()
  end

如果将字符串转换为字素,则可以测量它们占用了多少字节。然后,只需要“吃”出尽可能多的字素即可。

示例:

iex(1)> byte_size("á̀̃é̀̃")       
14
iex(2)> T.take_bytes("á̀̃é̀̃", 6)        
""
iex(3)> T.take_bytes("á̀̃é̀̃", 7)
"á̀̃"
iex(4)> T.take_bytes("á̀̃é̀̃", 14)
"é̀̃á̀̃"
iex(5)> T.take_bytes("á̀̃é̀̃", 13)
"á̀̃"

答案 2 :(得分:0)

只是出于好奇:

for <<c :: utf8 <- "abcdé">>, reduce: "" do
  acc when byte_size(acc <> <<c :: utf8>>) <= 5 ->
     acc <> <<c :: utf8>>
  acc ->
     acc
end
#⇒ "abcd"

或者,甚至更好(但不太正确):

for <<c <- "abcdé">>,
  reduce: "",
  do: (acc when c < 128 -> acc <> <<c>>; acc -> acc)
#⇒ "abcd"

for <<c <- "abcde">>,
  reduce: "",
  do: (acc when c < 128 -> acc <> <<c>>; acc -> acc)
#⇒ "abcde"

NB 这个结果无法产生正确的结果,以及此处发布的其他两个答案;主要是因为没有针对所述问题的正确答案。