从 unicode 字符串中获取随机 emoji/character
Getting a random emoji/character from a unicode string
我的目标是在 F# 中从列表中获取随机表情符号。
我是这样开始的:
let pickOne (icons: string) : char = icons.[Helpers.random.Next(icons.Length)]
let happySymbols = ""
let sadSymbols = ""
那是行不通的,因为:
"".Length
是 returning 44 作为长度 returns 字符串中的字符数,这不适用于 unicode 字符。
我不能只除以 2,因为有时我可能会在字符串中添加一些单字节字符。
索引也不起作用:
let a = ""
a.[0]
不会 return 但我得到了一些未知的字符符号。
因此,B 计划是:让我们将其设为数组而不是字符串:
let a = [| ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; '' |]
这不是编译,我得到:
Parse error Unexpected quote symbol in binding. Expected '|]' or other token.
这是为什么?
无论如何,我可以制作一个字符串列表并让它工作,但我很好奇:有没有 "proper" 方法让第一个工作并从 unicode 中获取随机 unicode 字符字符串?
.NET 中的所有字符串都是 16 位 unicode 字符串。
那就是char
的定义:
Represents a character as a UTF-16 code unit.
所有字符占用最小编码大小(UTF-16 为 2 个字节),最多不超过所需的字节数。表情符号不适合 2 个字节,因此它们对齐到 4 个字节或 2 个字符。
那么解决方法是什么?对齐(4)所有的东西! (在这里插入 GCC 笑话)。
首先我们将所有内容转换成UTF32
:
let utf32 (source: string) =
Encoding.Convert(Encoding.Unicode, Encoding.UTF32, Encoding.Unicode.GetBytes(source))
然后我们可以任意挑选"character":
let pick (arr: byte[]) index =
Encoding.UTF32.GetString(arr, index * 4, 4)
测试:
let happySymbols = "YTHO"
pick (utf32 happySymbols) 0;;
val it : string = ""
> pick (utf32 happySymbols) 22;;
val it : string = "Y"
对于实际长度,只需 div 乘以 4。
let surpriseMe arr =
let rnd = Random()
pick arr (rnd.Next(0, arr.Length / 4))
嗯嗯
> surpriseMe (utf32 happySymbols);;
val it : string = ""
Asti 的回答符合您的目的,但我对我们在这个问题上的进展不太满意。我想我被答案中的 "proper" 这个词给迷住了。在各个地方进行了大量研究之后,我对这个方法感到好奇String.EnumerateRunes, which again lead me to the type Rune。该类型的文档对正确的字符串处理以及 .NET 中 Unicode UTF-8 字符串中的内容特别有启发性。我也在 LINQPad 上试验过,得到了这个。
let dump x = x.Dump()
let runes = "abcABCæøåÆØÅ₅茨茧茦茥".EnumerateRunes().ToArray()
runes.Length |> dump
// 20
runes |> Array.iter (fun rune -> dump (string rune))
// a b c A B C æ ø å Æ Ø Å ₅ 茨 茧 茦 茥
dump runes
// see screenshot
let smiley = runes.[13].ToString()
dump smiley
//
我的目标是在 F# 中从列表中获取随机表情符号。
我是这样开始的:
let pickOne (icons: string) : char = icons.[Helpers.random.Next(icons.Length)]
let happySymbols = ""
let sadSymbols = ""
那是行不通的,因为:
"".Length
是 returning 44 作为长度 returns 字符串中的字符数,这不适用于 unicode 字符。 我不能只除以 2,因为有时我可能会在字符串中添加一些单字节字符。
索引也不起作用:
let a = ""
a.[0]
不会 return 但我得到了一些未知的字符符号。
因此,B 计划是:让我们将其设为数组而不是字符串:
let a = [| ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; ''; '' |]
这不是编译,我得到:
Parse error Unexpected quote symbol in binding. Expected '|]' or other token.
这是为什么?
无论如何,我可以制作一个字符串列表并让它工作,但我很好奇:有没有 "proper" 方法让第一个工作并从 unicode 中获取随机 unicode 字符字符串?
.NET 中的所有字符串都是 16 位 unicode 字符串。
那就是char
的定义:
Represents a character as a UTF-16 code unit.
所有字符占用最小编码大小(UTF-16 为 2 个字节),最多不超过所需的字节数。表情符号不适合 2 个字节,因此它们对齐到 4 个字节或 2 个字符。
那么解决方法是什么?对齐(4)所有的东西! (在这里插入 GCC 笑话)。
首先我们将所有内容转换成UTF32
:
let utf32 (source: string) =
Encoding.Convert(Encoding.Unicode, Encoding.UTF32, Encoding.Unicode.GetBytes(source))
然后我们可以任意挑选"character":
let pick (arr: byte[]) index =
Encoding.UTF32.GetString(arr, index * 4, 4)
测试:
let happySymbols = "YTHO"
pick (utf32 happySymbols) 0;;
val it : string = ""
> pick (utf32 happySymbols) 22;;
val it : string = "Y"
对于实际长度,只需 div 乘以 4。
let surpriseMe arr =
let rnd = Random()
pick arr (rnd.Next(0, arr.Length / 4))
嗯嗯
> surpriseMe (utf32 happySymbols);;
val it : string = ""
Asti 的回答符合您的目的,但我对我们在这个问题上的进展不太满意。我想我被答案中的 "proper" 这个词给迷住了。在各个地方进行了大量研究之后,我对这个方法感到好奇String.EnumerateRunes, which again lead me to the type Rune。该类型的文档对正确的字符串处理以及 .NET 中 Unicode UTF-8 字符串中的内容特别有启发性。我也在 LINQPad 上试验过,得到了这个。
let dump x = x.Dump()
let runes = "abcABCæøåÆØÅ₅茨茧茦茥".EnumerateRunes().ToArray()
runes.Length |> dump
// 20
runes |> Array.iter (fun rune -> dump (string rune))
// a b c A B C æ ø å Æ Ø Å ₅ 茨 茧 茦 茥
dump runes
// see screenshot
let smiley = runes.[13].ToString()
dump smiley
//