@finbheara/names

中文文档
0.31.0发布于 2026/11/07MITTypeScriptES Module近 30 天下载 3357

个人、学校和地名、姓氏-粒子词汇、分类词和人名正常化词典

中文使用文档
文档目录18 节
  1. 入境点
  2. 将名称正常化
  3. 级别
  4. 一个被损坏的指纹
  5. 工厂
  6. 文件的名称顺序
  7. 将拆分器对应于已公布的指纹
  8. 两个名字如何关联
  9. 只有一个名字,一个有名的
  10. 其它语言的指定名称表
  11. 密码和屏蔽键
  12. 作为数据库列的名称
  13. 词典
  14. 名称.txt
  15. 分类一个短语
  16. 测量名称流
  17. 捐款
  18. 许可证

@ finbhea/ 名称

实际打印的人名: 解析、 正常化、 比较、 分解 从学校和地名.

  • 拼音词典 (单位:千美元)names.txt: ~15 000人 姓名、地点、学校和 多词短语,每个标出它是什么.
  • 姓氏-粒子词汇数字 : Mac, (中文(简体) ), Ní, (中文(简体) ), O, (中文(简体) ), van, (中文(简体) ), de 剩下的,还有.. 每个显示一个拼写.
  • 人名规范化: 一个打印单元格, a PersonName 出来,有一个 canonial 显示窗体,文件密钥和匹配密钥.
  • 一个词组分类器:这个字符串是一个人,一个学校或一个地方,在哪里 人结束 学校开始?
  • 计量工具:通过上述所有内容运行一串名称流,并查看其内容 无法识别.

它建立在爱尔兰舞蹈比赛的结果单上 一个舞者的名字 以 O'RERVTON, MOIRA, (中文(简体) ), Moira ORervton 财务报告和审定财务报表 Moira O Rervton和学校的名字 连接在舞者身上 规则一般为盎格鲁语,爱尔兰语和欧洲语名.

npm install @finbheara/names

无害环境管理,节点为 22.3 或 Bun为 1.4.3. MIT。 无条目进口a node: 模块,因此每个条目 用于浏览器或工人的捆绑 Lexicon.load,它读取文件,需要节点 或Bun在呼叫时间.

入境点

只导入您使用的; /lexicon, (中文(简体) ), /particles, (中文(简体) ), /normalize 财务报告和审定财务报表 /phonetic 从不装入 分类器的开花桌子.

导入什麽
@finbheara/names/normalizePersonName,它的工厂,比较,编曲,列表
@finbheara/names/lexiconnames.txt 解析:旗帜、多词短语、拼写、角色
@finbheara/names/particles粒子词汇
@finbheara/names/classifier人/学校/地点分类和分类
@finbheara/names/phonetic双元音:一个单词作为密钥听起来如何
@finbheara/names/measure普查和分类评价
@finbheara/names以上各项
@finbheara/names/names.txt原始词典

将名称正常化

import { isNoNamePrint, personName } from "@finbheara/names/normalize";

const n = personName("WYRKOW NÍ MHAOLVARNA");
n.nn2;           // "NiMhaolvarna<<Wyrkow"      canonical display form
n.nn3;           // "NIMHAOLVARNA<<WYRKOW"      filing key
n.nn4;           // "NIMHAOLVARNA<WYRKOW"       order-free matching key
n.surnameKey();  // "NIMHAOLVARNA"
n.givenName();   // "WYRKOW"
n.surname;       // { particles: ["NÍ"], base: "MHAOLVARNA", tradition: "i", ... }
n.isPerson();    // true

personName("ORERVTON, MOIRA", "surname-first").nn2;  // "O'Rervton<<Moira"
personName("Foireann A").isTeam();                  // true: a team, not a person
personName("Kelsey Pearraillina - BN2018").refusal;       // { rule: "refuse-digit", ... }
personName("N/A").printsNoName();                   // true: a placeholder, no name printed
personName("").isEmpty();                           // true: nothing printed at all
isNoNamePrint("Not known");                         // true, from the print alone (no parse)

每个输入都有一个 PersonName; 一个没有人名的单元格 拒绝,而不是抛出: isPerson() 是虚假的, refusal 从NN2到NN2的每个关卡都读到 PersonName.REFUSED (单位:千美元)"!!!INVALID") (中文(简体) ). 空牢房既不是个人也不是拒绝: 它会回答 isEmpty()。 。 。 . printsNoName() 对空单元格、无字母单元格来说是真实的 (单位:千美元)???)和一个占位符(N/A, (中文(简体) ), TBA, (中文(简体) ), Unknown, (中文(简体) ), Not known),无论哪个规则拒绝.

级别

职等实值大小写口音顶点字段顺序
nn0准确的页上说保留保留保留保留
nn1nn0 使用白空格、 引用、 控制字节和一个命名的腐败修复保留保留已正常化保留
nn2条形显示形式(Surname<<Given<Middle(中文(简体) )来源ASC 二届理事会保留保留
nn3归档密钥上层ASC 二届理事会丢弃保留
nn4匹配的密钥 : 两个指纹是否同名 ?上层ASC 二届理事会丢弃丢弃

坚持关卡字符串,绝不是对象 : nn2 显示, nn3 作为关键。 读取存储 nn2 带回 personNameFromIcao(nn2) (或 factory.fromIcao) (中文(简体) ). 合同满了 docs/NAME-NORMALIZATION.md。 。 。 .

一个被损坏的指纹

其字节在路上出错(UTF-8读作Windows 1252,读取两次,读取为 Mac OS Roman,一个被丢弃的字节,一个被迷路的控制)这样说. corruption 每个运行的名称,以及 水平读取其修复,同时 nn0 保存原始打印 :

const n = personName("Méabh Varane", "given-first");
n.nn0;              // "Méabh Varane"
n.nn1;              // "Méabh Varane"
n.nn2;              // "Varane<<Meabh"
n.corruption?.kind; // "utf8-as-cp1252"
n.corruption?.spans; // [{ kind: "utf8-as-cp1252", at: 1, raw: "é", repair: "é", confidence: 0.98 }]

diagnoseNameCorruption(print, knownNameOf(lexicon)) 是赤线的相同答案。 A 类 prot 字节被读取为对照词典的通配符,并取出一个丢失的字母(U+FFFD)并 从来没有填满。 种类和信心在 docs/NAME-NORMALIZATION.md, (中文(简体) ), 一个被损坏的指纹。 。 。 .

工厂

personName 是默认工厂的短手: 一个笼罩在承诺的工厂 names.txt。当您需要其他选项时,请自行制作;工厂的选项是固定的 当它是制造的, 没有工厂可以改变别人的答案.

import { createCachingPersonNameFactory, createPersonNameFactory } from "@finbheara/names/normalize";

const names = createCachingPersonNameFactory({
  lexicon: myLexicon,             // a Lexicon or a (key) => spelling lookup; null for rules only
  traditions: null,               // no tradition lookup
  parenthetical: (aside) =>       // what "( … )" or "\" … \"" in a name cell means
    aside === "Ontario" ? { refuse: "refuse-location-alias" } : "strip",
  capacity: 100_000,              // memo size; 0 disables the memo
});
names.parse("Anna (Ontario) Mailtina").isPerson();  // false
names.parse("Lena (Xiaoyu) Zumock").nn2;           // "Zumock<<Lena"
names.stats();                                   // { hits, misses, evictions, size, capacity }

const uncached = createPersonNameFactory();      // parses every call

默认 parenthetical 处理器全边条 : Pundeallina "Katie" Foxe 实值 Foxe<<Pundeallina。 。 。 .

一个缓冲工厂每个打印一个条目, 和它的顺序是: 打印读取 与命令 unknown 和再次的顺序 决心是一分一分 对象。 过去 capacity (默认) DEFAULT_PERSON_NAME_CAPACITY,262,144) 最少 最近使用的入口被逐出; stats().evictions 数起他们.

共享默认工厂的容量可以设定为每个进程一次,在任何程序之前 透过它。 能力是唯一的选择,因为它是唯一的选择 未改变答案 :

import { configureDefaultPersonNameFactory, personName } from "@finbheara/names/normalize";

configureDefaultPersonNameFactory({ capacity: 1_000_000 }); // ~1 KB an entry
personName("Moira O'Rervton");
configureDefaultPersonNameFactory({ capacity: 10 });        // throws: already made

一旦默认工厂存在,它就会抛出, 无论是先前的呼叫还是第一个 personName, (中文(简体) ), personNameFromIcao 或者说 defaultPersonNameFactory() 对.

文件的名称顺序

deriveNameFormat 读取 ONE 文件的名称单元格(结果表、名册、 并说它是用哪个顺序打印的,作为概率 First Last, (中文(简体) ), Last, First 财务报告和审定财务报表 Last First,与 "unknown" 在那里,没有人能清除阈值或 文档打印两个命令。 它还提出报告 hasSchool 财务报告和审定财务报表 hasLocation (做大多数单元格) 随身携带一个学校或一个地方的名字之后?),每个指纹读取,所以打电话者可以脱去 解析前的那些部分.

import { createSegmenter } from "@finbheara/names/classifier";
import { Lexicon } from "@finbheara/names/lexicon";
import { deriveNameFormat, nameFormatOrder, readNameCell } from "@finbheara/names/normalize";

// invented names, in a lexicon of their own
const lexicon = Lexicon.fromText("Zelvine:F\nOramie:F\nTalwyn:F\nQuorrish:L\nVantrell:L\nOspindle:L\nZandrel:G");
const segmenter = createSegmenter(lexicon);   // optional: reads the school part; same lexicon
const doc = deriveNameFormat(
  ["Quorrish, Zelvine", "Vantrell, Oramie - Zandrel", "Ospindle, Talwyn", "Quorrish, Oramie", "Vantrell, Talwyn"],
  { lexicon, segmenter },
);
doc.verdict;                    // "Last, First"
nameFormatOrder(doc.verdict);   // "surname-first": pass it as the document's declared order
doc.readings[1].name;           // "Vantrell, Oramie"
doc.readings[1].location;       // "Zandrel"

deriveNameFormat(["QUORRISH ZELVINE", "VANTRELL ORAMIE"], { lexicon }).verdict;  // "unknown": too few
readNameCell("QUORRISH ZELVINE", { lexicon }).order;                           // "surname-first:two-token"

判决是呼叫者对文件的声明; 将行组为 文档是呼叫者的.

宣布的命令胜过逗号;逗号只在没有宣布的情况下决定:

personName("Fennick, Orla", "given-first").nn2;  // "Orla<<Fennick": the declaration decides
personName("Fennick, Orla", "unknown").nn2;      // "Fennick<<Orla": the comma decides

在给定的第一个页面上,一个逗号在给定的第一个名称内比在某个名称内更经常被指点 一个倒置。 一个知道页面混合的呼叫者 Surname, Given 单元格为给定第一个 通行证 unknown 对于该页,所以逗号决定每个单元格. deriveNameFormat 报告此页面为 unknown (单位:千美元)mixed其中有许多人(6人中有3人) 单元格)和 nameFormatOrder 地图到 unknown; 单个流出单元格( 6个中的1个) 仍然 来源 First Last。 。 。 . bun run names order <file> 为文件打印相同的 名称单元格,每行1个。 规格是 docs/NAME-NORMALIZATION.md。 。 。 .

将拆分器对应于已公布的指纹

A 类 Last, First 打印自己的姓氏. buildAnchorIndex 从 打印其文件宣布其顺序, anchoredSurname 找到打印 同一名称的顺序 primedVerdict 说是否一个拆分者放置了边界 在这里。 分裂者是一个争论,所以故意错误的控制(edgeOnlySplit, (中文(简体) ), compoundLessSplit)显示栏可以失败. unprimedTally 按顺序猜测 扣留的申报,以及 clearsUnprimedFloor 将其平衡率与 UNPRIMED_FLOOR。 。 。 .

import {
  anchoredSurname, buildAnchorIndex, edgeOnlySplit, primedVerdict, splitPersonName,
} from "@finbheara/names/normalize";

const prints = [
  { name: "van der Quell, Pealling", declared: "Last, First" as const },
  { name: "Pealling van der Quell", declared: "First Last" as const },
];
const anchor = anchoredSurname(prints[1], buildAnchorIndex(prints));  // "vanderquell"
primedVerdict(prints[1], anchor, splitPersonName).verdict;             // "consistent"
primedVerdict(prints[1], anchor, edgeOnlySplit).verdict;               // "inconsistent"
import {
  createGivenFamilyList, createNameIndex, createNameKinship, givenFamilyTable, nameKinship,
  personName,
} from "@finbheara/names/normalize";

nameKinship(personName("Kate Smith"), personName("Katherine Smith"));
// { relation: "candidate", via: ["given-family"], reason: "middles-equal", gateSafe: true }
nameKinship(personName("Mary Larson"), personName("Mary Conley-Larson")).via;  // ["surname-part"]
nameKinship(personName("Mary Larson"), personName("Mary Carlson")).reason;     // "surname-differs"
nameKinship(personName("Kate M Smith"), personName("Katherine Conley-Smith")).via;
// ["surname-part", "given-family", "middle-absent"]
nameKinship(personName("Connor Smith"), personName("Conor Smith")).via;       // ["given-variant"]
nameKinship(personName("Evie Smith"), personName("Genevieve Smith"));
// { relation: "candidate", via: ["given-family-not-gate"], reason: "middles-equal", gateSafe: false }
nameKinship(personName("Beth Smith"), personName("Bethany Smith"));   // the extended family list
// { relation: "candidate", via: ["given-maybe"], reason: "middles-equal", gateSafe: false }
nameKinship(personName("Grace Zumock"), personName("Ailbhe Grace Zumock"));  // a middle name used
// { relation: "candidate", via: ["given-middle"], reason: "middles-equal", gateSafe: false }

// four opt-in readings, each off by default: a suffix one side lacks, a run of initials,
// a hyphenated first name with its first half spelt another way, an Irish surname form
const wide = createNameKinship({
  suffixAbsent: true, initialRuns: true, joinedVariants: true, surnameForms: true,
});
wide(personName("Lena Zumock"), personName("Lena Zumock II")).via;      // ["suffix-absent"]
wide(personName("JR Zumock"), personName("Zumock, Joseph R.")).via;     // ["given-initials"]
wide(personName("Ann Marie Zumock"), personName("Zumock, Anne-Marie")).via;
// ["given-joined", "given-family"]
wide(personName("Lena Nolan"), personName("Ó Nualláin, Lena")).via;     // ["surname-form"]

// the given-name tolerance is a list of providers, asked in order
const tableOnly = createNameKinship({ given: [givenFamilyTable] });
tableOnly(personName("Beth Smith"), personName("Bethany Smith")).reason;  // "given-differs"
const common = createNameKinship({
  given: [givenFamilyTable, createGivenFamilyList({ maxTier: 1 })],  // common forms only
});
common(personName("Maggie Smith"), personName("Marjorie Smith")).reason;  // "given-differs"

const index = createNameIndex<number>("nn3");   // a NameMap with a tolerant lookup
index.set(personName("Mary Conley-Larson"), 1).set(personName("Mary Carlson"), 2);
index.get(personName("Mary Larson"));            // undefined: get stays exact
index.related(personName("Mary Larson"));        // [{ name: Conley-Larson<<Mary, value: 1, kinship: … }]

屏蔽一组记录(两个记录可以打印出一个名字),将记录放在屏蔽器中并取出 双对; 每对相关的对来一次, 不比较每对:

import { createNameBlocker, personName } from "@finbheara/names/normalize";

const blocker = createNameBlocker<string>();
blocker
  .add("row-1", personName("Mary Larson"))
  .add("row-2", personName("Mary Conley-Larson"))
  .add("row-3", personName("Mary Larson"))
  .add("row-4", personName("Mary Carlson"));
for (const { a, b, kinship } of blocker.pairs()) console.log(a.id, b.id, kinship.relation);
// row-1 row-3 same
// row-1 row-2 candidate
// row-2 row-3 candidate

candidate 它说两个指纹可能就是一个人. via 列表中 耐用对子,和 gateSafe 当其中任何一个都是一扇门时,是虚假的 自己承认吧.

A 类 ? (或U+FFFD)在平面上是一个丢失的被捕获的字母. 关卡保持什么打印 保留,以及 nameKinship 读取每个 ? 当指纹有分歧时 没有它:

import { lostLetterForm, nameKinship, personName } from "@finbheara/names/normalize";

nameKinship(personName("Zoë Bérard"), personName("Zo? B?rard"));
// { relation: "candidate", via: ["lost-letter"], reason: "middles-equal", gateSafe: false }
personName("Orlaith N? Varraigh").nn2;              // "NiVarraigh<<Orlaith": `N?` can only be Ní
lostLetterForm(personName("Zo? B?rard")).surname;   // "B?RARD": NN3's field, the `?` kept

一个名字读取西班牙语的方式(给定的名字、父亲的姓和母亲的姓)是选入的。 这里 默认关系表示 different, (中文(简体) ), spanishNames: true 阅读每个印刷品 每一个方式可能切割, 保持由粒子结合的化合物或 y 并且将完整形式与较短形式联系起来:

import { createNameIndex, createNameKinship, personName } from "@finbheara/names/normalize";

const spanish = createNameKinship({ spanishNames: true });
spanish(personName("Ana Inés Varrondo Quelmar"), personName("Inés Varrondo"));
// { relation: "candidate", via: ["surname-maternal", "given-middle", "spanish"],
//   reason: "middle-absent", gateSafe: false }
spanish(personName("Sofía Ostrevo Landar"), personName("SOFIA OSTREVO")).via;
// ["surname-maternal", "spanish"]
spanish(personName("Ailbhe Grace Zumock"), personName("Ailbhe Grace")).relation;
// "different": `Grace` is a given name, never the first surname
spanish(personName("Renata Ruelas y Terzán"), personName("Renata Ruelas")).relation;
// "different": `Ruelas y Terzán` is one surname

const index = createNameIndex<number>("nn3", { spanishNames: true });
index.set(personName("Ana Inés Varrondo Quelmar"), 1);
index.related(personName("Inés Varrondo")).map((m) => m.value);  // [1]

由OCR从扫描页读取的名字可能带有识别器混淆的格言:一个小写 l 资本 I, (中文(简体) ), rn 页:1 m。 。 。 . ocrConfusion(a, b) 比较两个字,回答: 运行它读作他们的可信任, [] 如果文字已经同意作为NN3读取,或 null它不产生任何结果,也不产生关键:OCR_CONFUSABLES页:1 读取 glyph, 包含大小写, 包没有设定阈值, 所以调用者计算 经营或拒绝一个班级本身. createNameKinship({ ocrConfusables: true }) 读取字段 字段,关系会说 different,通过 ocr-glyph (从来不是安全的大门),和每 回答它用它携带的运行作为 confusions· ; createNameIndex 财务报告和审定财务报表 createNameBlocker 选择相同的选项, 因此每个匹配都带有相同的数组 :

import {
  OCR_CONFUSABLES, createNameIndex, createNameKinship, ocrConfusion, personName,
} from "@finbheara/names/normalize";

ocrConfusion("Quamby", "Quarnby");  // [{ class: "rn-m", a: "m", b: "rn", at: 3 }]
ocrConfusion("lvarra", "Ivarra");   // [{ class: "I-l", a: "l", b: "I", at: 0 }]
ocrConfusion("LVARRA", "IVARRA");   // null: a capital L is no capital I's confusable
ocrConfusion("Quarnby", "QUARNBY"); // []: equal as NN3 reads them

const ocr = createNameKinship({ ocrConfusables: true });
ocr(personName("Kate Quamby"), personName("Kate Quarnby"));
// { relation: "candidate", via: ["ocr-glyph"], reason: "middles-equal", gateSafe: false,
//   confusions: [{ class: "rn-m", a: "m", b: "rn", at: 3, field: "surname", index: 0 }] }
const noRn = createNameKinship({
  ocrConfusables: OCR_CONFUSABLES.filter((r) => r.class !== "rn-m"),
});
noRn(personName("Kate Quamby"), personName("Kate Quarnby")).relation;  // "different"

const index = createNameIndex<number>("nn3", { ocrConfusables: true });
index.set(personName("Kate Quarnby"), 1);
index.related(personName("Kate Quamby")).map((m) => m.kinship.confusions);  // [[{ class: "rn-m", … }]]

只有一个名字,一个有名的

import { createNameRoster, givenOnlyName, personName } from "@finbheara/names/normalize";

givenOnlyName("Lena").nn2;     // "<<Lena": the caller declares the print given-only
personName("Lena").isPerson(); // false: undeclared, one word is still refused
givenOnlyName("Lena Z.").nn2;  // "Z<<Lena": a trailing single letter is the surname initial

const roster = createNameRoster(
  ["Lena Zumock", "Mairéad Rervton", "Lena Brambleton", "Éilis Zumock"].map((p) => personName(p)),
);
roster.match(givenOnlyName("Mairead")); // { kind: "unique", name: Rervton<<Mairead }
roster.match(givenOnlyName("eilis"));   // { kind: "unique", name: Zumock<<Eilis }
roster.match(givenOnlyName("Lena"));    // { kind: "ambiguous", names: [Brambleton<<Lena, Zumock<<Lena] }
roster.match(givenOnlyName("Lena Z"));  // { kind: "unique", name: Zumock<<Lena }
roster.match(givenOnlyName("Orla"));    // { kind: "none", reason: "no-candidate" }

仅 unique 这是一个答案:名册从不挑选候选人。 打印匹配 以 nameKinship,其中缺少姓氏(surname-absent)或初始数据 (单位:千美元)surname-initial)不能排除一对夫妇出局,从来就没有门安全. 默认关系使用 指定名称的目录,所以 Kate 发现 Katherine; 通过 { kinship: createNameKinship({ given: [] }) } 以匹配给定的名字。 回答没有 取决于设定的顺序.

其它语言的指定名称表

后面的桌子 后面的桌子 后面的桌子 givenFamilyTable 财务报告和审定财务报表 givenFamilyList 打印为 JSON, 给消费者 这不是JavaScript :

npx @finbheara/names tables given-name > given-name-tables.json   # or bunx

--output json 财务报告和审定财务报表 --schema 1 是默认的。 PRINTED表格是合同:a 只要软件包能保持它的形状 新的形状就是新的 计划,所以今天写的命令 继续工作。 表格中存储的文件是 不是它的一部分。 司马一是

{
  "$comment": [ /* how to read it */ ],
  "table": "given-name", "schema": 1,
  "variants":  { "CONNOR": ["CONOR"], … },        // canonical -> its other spellings
  "families":  { "CATHERINE": ["KATE", …], … },   // the curated gate tier: root -> forms
  "notAtGate": ["MEGAN", …],                      // forms a gate must not admit as forms
  "extended":  { "BETHANY": { "BETH": 1 }, … }    // root -> form -> tier (1 common .. 3 rare)
}

读它像图书馆一样 $comment 说:读出每个名字 拼写第一; 两个名称仅在共享根时关联, 一个表单满足 EveryY root it 坐在下面,没有什么是过渡性的(EVIE 开会 EVE 财务报告和审定财务报表 EVA,不分别满足 (其他部分)。 一个共享的根是 given-family 除非一个名字只作为 notAtGate 形式; 名字是根本身总是通过。 一个 extended 双层是稀有的 成员,根数为 1. 为避免比较每对,索引每个名称下 它的每个根 和比较在根, 从来没有一个根 每个名字.

密码和屏蔽键

import { doubleMetaphone } from "@finbheara/names/phonetic";
import { initialsBlock, metaphoneBlocks, personName, surnameBlock } from "@finbheara/names/normalize";

doubleMetaphone("SMITH");      // ["SM0", "XMT"]  primary, secondary
doubleMetaphone("KAVANAGH");   // ["KFNK", "KFNK"]

const n = personName("Moira O'Rervton");
surnameBlock(n.surnameKey());                     // "ORERVTON"  A-Z letters only
metaphoneBlocks(n.surnameKey());                  // ["ARRF"]
initialsBlock(n.givenFields()[0] ?? "", n.surnameKey());  // "MO"

doubleMetaphone 普通口音密钥:印刷名和转写口语 语言被问到同样的问题。 三个块键桶名值 比较和决定无;每个答案 null (或 []无所事事的地方 桶装上,所以一个自相残杀 永远不能把空心.

作为数据库列的名称

import { NAME_COLUMNS, nameColumns, personName } from "@finbheara/names/normalize";

NAME_COLUMNS;  // ["nn0", …, "nn4", "surname_key", "given_key", "blk_surname", "blk_initials",
               //  "blk_metaphone", "blk_metaphone_alt"]
nameColumns(personName("Moira O'Rervton"));
// { nn0: "Moira O'Rervton", …, nn3: "ORERVTON<<MOIRA", surname_key: "ORERVTON",
//   given_key: "MOIRA", blk_surname: "ORERVTON", blk_initials: "MO", blk_metaphone: "ARRF", … }

每个密钥一个编码器一个存储索引,不依赖数据库。 级别栏 位点 createNameMap 将名称存档于, null 对于一个没有名字的指纹, 因此,一个级别上的地图检索就是一个列上的一等.

词典

import { Lexicon } from "@finbheara/names/lexicon";

const lex = Lexicon.default();              // the committed names.txt, parsed on first use
lex.getNameFlags("Murphy");                 // "LT": a surname, and a tradename
lex.getNameFlags("New York");               // "BG": a multi-word place
lex.matchBigramContinuations("New");        // [["south","wales"], ["york","city"], ..., ["york"], ...]
lex.displaySpelling("MACDONALD");           // "MacDonald"

Lexicon.load("./my-names.txt");             // your own file, same format (Node and Bun)
Lexicon.fromText("Aoife:F\nKowalski:L6\n");

名称.txt

每行一条, Name:FLAGS。 。 。 . # 开始评论。 没有旗帜的一行是女性 名称。 旗帜对大小写有敏感认识并结合(Kelly:AF, (中文(简体) ), New York:BG) (中文(简体) ).

旗帜含义
F M N女性 / 男性 / 性别中性名称
L姓氏
A含糊不清:既被视为一个给定的名字,又被视为一个姓氏
G地点
T商品名称:学校或教师
C概念词 (River(中文(简体) )
B多词条目( bigram 或 三相)
S一种已知的字型,保存所以被识别
X从显示器的回程检查中排除
D指定名称 diminutive table holds (Kate:FD);一个标记,像 S 财务报告和审定财务报表 X

数字后 L 或者说 A 是一个 传统脚注数字 : 1 亚美尼亚人, 2 日耳曼语, 3 伊比利亚人, 4 爱尔兰人/加利克人, 5 北欧, 6 斯拉夫语( O)Kowalski:L6) (中文(简体) ). 一个索引是 永久发行;新的传统取下一份免费索引.

分类一个短语

import { phraseClassifier } from "@finbheara/names/classifier";

const pc = phraseClassifier();               // over the committed lexicon
pc.classifyNameNormalized("Quorrish Academy of Irish Dance");
// { scores: { person: 0.00, school: 1.00, location: 0.00 }, confidence: 1.00, category: "school" }
pc.segment("Mary Kate O Trurane Quorrish Academy");
// { type: "PS", person: ["Mary","Kate","O","Trurane"], school: ["Quorrish","Academy"], boundary: 4, ... }

一个后勤后退分级器和一个分级器 超过训练有素的重量和开花过滤器 公开姓名和地点名单data/bloom/MANIFEST.json) (中文(简体) ). 它是为 多词 短语; 对于单个符号,请询问词典.

宣布名称顺序的平面图( E)given-first 或者说 surname-first告诉 分类器是这样,然后分类器读取其单元格的重量只安装在 宣布该命令的文件。 在姓氏第一页,名称栏中的逗号 将姓氏与给定姓名区分开来:

pc.getNameCategory(cell, "surname-first"); // the order the document declares
pc.getNameCategory(cell);                  // no order: the same as "unknown"

通过文档宣布的命令, 永远不要猜测: 命令读取单元格本身 (单位:千美元)inferNameOrder)不是一个声明,所以它不是对分类器的输入. 与 没有命令,或者 unknown答案正是没有争论的答案. classifyName, (中文(简体) ), classifyNameNormalized, (中文(简体) ), getNameCategory, (中文(简体) ), classifyBoundary 编辑 is… 测试(之后) threshold拿着 垃圾拒绝和地点规则的答案 每一个命令下首先.

模特总是从人、学校或地方挑一个 无此内容的文本( 页 footers,标题)可以在前面声明;整个短语匹配忽略大小写, 间距和分数, 分数为零, 分数为零 :

const pc = phraseClassifier(undefined, { garbageVocab: ["Results are provisional (c)"] });
pc.classifyNameNormalized("RESULTS ARE PROVISIONAL (C)");
// { scores: { person: 0, school: 0, location: 0 }, confidence: 0, category: "none" }

测量名称流

npx names-census < names.txt-or.jsonl           # one name per line, or JSON lines
npx names-census --field=name --order-field=order --classify --limit=50 < rows.jsonl
import { createNameCensus } from "@finbheara/names/measure";

const census = createNameCensus();
for (const row of rows) census.add(row.name, row.order);
const report = census.report();
report.unknownTokens;  // words no lexicon entry knows, most printed first, with examples
report.unknownPairs;   // adjacent unknown words: candidate multi-word entries
report.refused;        // refusals by rule

未知的词是候选人 names.txt 增加数。 这几乎就是解决 每误读.

捐款

见 捐款额: 如何添加名称,门,分类器 方法和版本.

许可证

麻省理工学院Finbheata系统。 开花桌由第三方名单组成 来源在 data/bloom/MANIFEST.json。 。 。 .

版本与发布记录

@finbheara/names 共发布 34 个版本,首次发布于 2026/10/01;过去 12 个月发布了 34 个版本。

版本发布日期距今
0.31.0latest2026/11/077 天前
0.30.02026/10/2322 天前
0.29.02026/10/2322 天前
0.28.02026/10/2125 天前
0.27.12026/10/2025 天前
0.26.02026/10/1926 天前

关于 @finbheara/names 的常见问题

@finbheara/names 是什么?

个人、学校和地名、姓氏-粒子词汇、分类词和人名正常化词典

如何安装 @finbheara/names?

在项目目录运行 npm install @finbheara/names,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 names、names-census,可以用 npx names 直接运行。

@finbheara/names 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@finbheara/names 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@finbheara/names 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.3。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@finbheara/names 可以商用吗?

@finbheara/names 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@finbheara/names 的下载量有多少?

根据 npm 官方下载统计,@finbheara/names 在 2026/10/15 – 2026/11/13 这 30 天内被下载 3,357 次,日均约 112 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@finbheara/names 还在维护吗?

最新版本 0.31.0 发布于 2026/11/07(7 天前);至今共发布 34 个版本,其中过去 12 个月发布了 34 个;首次发布于 2026/10/01。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。