问题描述
我正在尝试使用人类可读的替换来匿名化生产数据 - 这不仅会掩盖实际数据,还会为其提供可调用的身份以供识别。 请帮助我如何在 Scala 中使用其他可发音的英语单词匿名化数据框列,如名字、姓氏、全名:
- 它必须将一个真实世界的名称转换为另一个可发音和可识别的真实世界名称。
- 必须可以分别转换名字、姓氏和全名,例如全名 = 用空格分隔的名字和姓氏。
- 它应该在每次迭代中为名称生成相同的匿名名称。
- 目标数据集将有超过一百万条不同的记录。
我曾尝试遍历名词和形容词词典以达到两个可发音单词的组合,但它不会给我一百万种不同的组合。 代码如下:
def anonymizeString(s: Option[String]): Option[String] = {
val AsciiUpperLetters = ('A' to 'Z').toList.filter(_.isLetter)
val AsciiLowerLetters = ('a' to 'z').toList.filter(_.isLetter)
val UtfLetters = (128.tochar to 256.tochar).toList.filter(_.isLetter)
val Numbers = ('0' to '9')
s match {
//case None => None
case _ =>
val seed = scala.util.hashing.MurmurHash3.stringHash(s.get).abs
val random = new scala.util.Random(seed)
var r = ""
for (c <- s.get) {
if (Numbers.contains(c)) {
r = r + (((random.nextInt.abs + c) % Numbers.size))
} else if (AsciiUpperLetters.contains(c)) {
r = r + AsciiUpperLetters(((random.nextInt.abs) % AsciiUpperLetters.size))
} else if (AsciiLowerLetters.contains(c)) {
r = r + AsciiLowerLetters(((random.nextInt.abs) % AsciiLowerLetters.size))
} else if (UtfLetters.contains(c)) {
r = r + UtfLetters(((random.nextInt.abs) % UtfLetters.size))
} else {
r = r + c
}
}
Some(r)
}
解决方法
“它不会给我一百万种不同的组合”
我不知道你为什么这么说。我刚刚在我的 Mac 上查看了 /usr/share/dict/words
,它有 234,371 个单词。这允许两个词的近 550 亿 个组合。
因此,只需将您的字符串散列到 Int
,取模 234,371
,然后映射到字典中的相应条目。
当然,字典中的一些单词看起来不太像名字(尽管仍然比你随机做的要好得多) - 例如“A”...但即使您要求该词至少包含 5 个字符,您也将剩下 227,918 个词 - 仍然绰绰有余。
另外请不要在get
上使用“naked Option
”...这太伤害我的审美了:(
class Anonymizer(dict: IndexedSeq[String]) {
def anonymize(s: Option[String]) = s
.map(_.hashCode % dict.size)
.map(dict)
}