C#中是否有任何算法可以将单词单数化?


106

c#中是否有任何算法可对单词进行单数化(英语复数),或者是否存在.net库来做到这一点(可能也使用不同的语言)?

Answers:


182

您还具有System.Data.Entity.Design.PluralizationServices.PluralizationService

更新:旧答案值得更新。现在也有Humanizer:https : //github.com/MehdiK/Humanizer


2
允许您重新分发或仅使用设计DLL吗?我之所以这样问,是因为我知道DevExpress的许可证禁止重新分发任何.design DLL。
Pierre-Alain Vigeant

58
使用ILSpy打开代码将显示一个名为EnglishPluralizationService的类,该类在其中定义了许多例外情况,使阅读更加有趣。我特别喜欢“
肺部显微显微术

7
我可以猜到是怎么添加的。测试人员向开发人员提交了一个错误,称它不适用于该单词。开发人员已修复它。双方都笑了起来。
merlinbeard 2013年

2
@MrKWatkins听起来更像是“ supercalifragilisticexpialidocious”
Corstian Boerman

1
人性化是一个很好的建议。在发现它存在之前,我当然会自己实施其中的15%。
凯西

18

我可以为世界语做到这一点,没有任何特殊情况!

string plural(string noun) { return noun + "j"; }

对于英语,这将是有益的,熟悉的规则名词的复数定期,以及名词的不规则复数。Wikipedia上有整篇关于英语复数的文章,也可能有一些有用的信息。


5
如果您输入动词或副词,则应将其抛出!
Timwi's

1
@马特:这当然适用于主格。我相信,对于精明的读者来说,将这种方法扩展到宾格是很简单的。
格雷格·休吉尔

14

尽管大多数ORM并不完美,但大多数情况下都是如此。我知道Castle有它的Inflector Class,您可能可以在周围翻阅。不过,“完美地”做到这一点并非易事(英语“规则”并不是真正的规则:)),因此这取决于您是否对“合理的猜测”方法感到满意。


根据您的建议,我搜索了“ Inflector”,并发现该andrewpeters.net/inflectornet与城堡之一基本相同
Ronnie

4
实际上,它不是基本相同,而是相同。
David Pfeffer

12

我用Java作弊-我希望能够为“有n个东西”生成正确的字符串,所以我写了这篇文章。很少重载的实用方法:

static public String pluralize(int val, String sng) {
    return pluralize(val,sng,(sng+"s"));
    }

static public String pluralize(int val, String sng, String plu) {
    return (val+" "+(val==1 ? sng : plu)); 
    }

像这样调用

System.out.println("There were "+pluralize(count,"something"));
System.out.println("You have broken "+pluralize(count,"knife","knives"));

不过,这仅涵盖一小部分语法,并未考虑测验,聚会,两半,鼠标,索引等单词。这是一个很好的第一步,但还有很多其他规则应该首先处理。
杰里米·S

4
@Jeremy:为什么不?:的println( “你已通过” + singularPlural(计数, “智力问答”, “测验”)+ “到目前为止”)
劳伦斯·多尔

我对这个问题的解释可能有所不同。我认为算法应该在没有开发人员任何提示的情况下确定复数形式,而您的方法将知道复数形式在开发人员身上的责任。
杰里米·S

3
@杰里米:因此,“我被骗了...”的领先优势-似乎并没有理由不赞成。
劳伦斯·多尔

1
同意 我也认为所提供的信息很有用,这就是为什么任何拒绝投票都不来自我的原因。我一般不反对“一个男人的垃圾...”的说法。
杰里米·S

10

我在.net(C#)中为此创建了一个微型库,称为Pluralizer(毫不奇怪)。

它可以使用完整的句子,就像String.Format一样。

它基本上是这样的:

var target = new Pluralizer();
var str = "There {is} {_} {person}.";

var single = target.Pluralize(str, 1);
Assert.AreEqual("There is 1 person.", single);

// Or use the singleton if you're feeling dirty:
var several = Pluralizer.Instance.Pluralize(str, 47);
Assert.AreEqual("There are 47 people.", several);

它还可以做更多的事情。在我的博客上阅读有关它的更多信息。在NuGet中也可用。



4
是的,该库仅包含单个单词,仅包含名词(尽管Pluralizer在内部使用该类)。该库使整个句子更易于编写。查看我的博客以获取更多示例。Pluralizer.Instance.Pluralize(“ {她} {正在} {各自} {家}。”,5)
杰·奎里多

肖恩·威尔逊(Shaun Wilson)-我的电脑目前在零件中。我急于将其备份,并将在一两天内更新。同时,nuget.org / packages?q = pluralizer
Jay Querido


5

由于问题是针对C#的,因此这是Software Monkey解决方案的一个不错的变体(有点“作弊”,但对我而言,确实是最实用且可重用的方式):

    public static string Pluralize(this string singularForm, int howMany)
    {
        return singularForm.Pluralize(howMany, singularForm + "s");
    }

    public static string Pluralize(this string singularForm, int howMany, string pluralForm)
    {
        return howMany == 1 ? singularForm : pluralForm;
    }

用法如下:

"Item".Pluralize(1) = "Item"
"Item".Pluralize(2) = "Items"

"Person".Pluralize(1, "People") = "Person"
"Person".Pluralize(2, "People") = "People"

3

亚音速3具有Inflector其通过打开给我的印象类PersonPeople。我查看了源代码,发现它自然会用硬编码列表作弊,但这实际上是用英语以及人类操作方式的唯一方法-我们记住每个单词的单数和复数,而不仅仅是应用规则。由于没有男性/女性(/中性)添加到混合中,所以要简单得多。

这是一个片段:

AddSingularRule("^(ox)en", "$1");
AddSingularRule("(vert|ind)ices$", "$1ex");
AddSingularRule("(matr)ices$", "$1ix");
AddSingularRule("(quiz)zes$", "$1");

AddIrregularRule("person", "people");
AddIrregularRule("man", "men");
AddIrregularRule("child", "children");
AddIrregularRule("sex", "sexes");
AddIrregularRule("tax", "taxes");
AddIrregularRule("move", "moves");

AddUnknownCountRule("equipment");

像设备示例一样,它说明了一些单词不具有多个等效项。如您所知,它可以Regex使用$ 1 进行简单替换。

更新:
看来Subsonic Inflector确实是Castle ActiveRecordInflector类!


2

MSDN上没有太多有关PluralizationService类的特定用法的文档,因此这里是一个单元测试类(NUnit),用于显示基本用法。请注意,底部的奇数测试用例表明,对于非标准的复数形式,服务并不完美。

[TestFixture]
public class PluralizationServiceTests
{
    [Test]
    public void Test01()
    {
        var service = PluralizationService.CreateService(CultureInfo.CurrentCulture);

        Assert.AreEqual("tigers", service.Pluralize("tiger"));
        Assert.AreEqual("processes", service.Pluralize("process"));
        Assert.AreEqual("fungi", service.Pluralize("fungus"));

        Assert.AreNotEqual("syllabi", service.Pluralize("syllabus")); // wrong pluralization
    }
}


1

使用Microsoft的Northwind示例数据库:

 System.Data.Entity.Design.PluralizationServices.PluralizationService.CreateService(new System.Globalization.CultureInfo("en-US"));

单数化不单数化“ Order_Details”,它以“ s。”结尾返回“ Order_Details” 。解决方法是什么?


1
这是一个问题,而不是问题的答案...但是Pluralize()和Singularize()仅适用于词典单词。有一种使用ICustomPluralizationMapping.AddWord添加单词的方法,但是至少对于我来说,当您可能有很多不真实的单词(如代码名称)时,这不是一个很好的解决方案。
tordal

@tordal谢谢,这正是我要提出的问题
乍得
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.