Есть ли в С # какой-либо алгоритм для единственного - множественного числа?


106

Есть ли какой-либо алгоритм в С # для сингулярности - множественного числа (на английском языке) или существует ли для этого библиотека .net (может быть также на разных языках)?

Ответы:


182

У вас также есть System.Data.Entity.Design.PluralizationServices.PluralizationService .

ОБНОВЛЕНИЕ : старый ответ заслуживает обновления. Теперь есть Humanizer: https://github.com/MehdiK/Humanizer


2
Хммм, вы разрешаете распространять или просто использовать Design DLL? Я спрашиваю об этом, потому что знаю, что лицензия DevExpress запрещает распространение любых DLL .design.
Пьер-Ален Вижан,

58
При открытии кода с помощью ILSpy отображается класс EnglishPluralizationService, в котором определено множество исключительных случаев, и поэтому его интересно читать. Мне особенно нравится «пневмоноультрамикроскопический силиковулканокониоз», который я постоянно использую в своих моделях сущностей ... 8o)
MrKWatkins

7
Я могу догадаться, как это было добавлено. Тестировщик сообщил об ошибке разработчика, говоря, что он не работает для указанного слова. Дев исправил это. Оба рассмеялись.
merlinbeard

2
@MrKWatkins Больше похоже на «supercalifragilisticexpialidocious»
Корстиан Боерман

1
Humanizer - отличная рекомендация. Я, конечно, сам реализовал около 15%, прежде чем обнаружил, что он существует.
Кейси

18

Я могу сделать это для эсперанто, без особых случаев!

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

Для английского языка было бы полезно ознакомиться с правилами для правильного множественного числа существительных , а также неправильного множественного числа существительных . Есть целая статья в Википедии об английском множественном числе , в которой тоже может быть полезная информация.


5
Вы должны заставить его бросить, если вы передаете глагол или наречие!
Timwi

1
@Matt: Конечно, это подходит для именительного падежа; Я верю, что распространить этот метод на винительный падеж не составит труда для проницательного читателя.
Greg Hewgill

14

Большинство ORM пытаются это сделать, хотя в целом они не идеальны. Я знаю, что у Касла есть свой Inflector Class, вы, вероятно, можете повозиться . Однако сделать это «идеально» - непростая задача (английские «правила» на самом деле не правила :)), поэтому все зависит от того, довольны ли вы подходом «разумного предположения».


Исходя из вашего предложения, я поискал "Inflector" и нашел этот andrewpeters.net/inflectornet, который, по сути, должен быть таким же, как и Castle one
Ронни

4
На самом деле это не то же самое, а идентичное.
Дэвид Пфеффер

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"));

Это охватывает только небольшие разделы грамматики, но не учитывает такие слова, как викторины, вечеринки, половинки, мыши, индексы и т. Д. Это хороший первый удар, но есть много других правил, которые, вероятно, следует обработать в первую очередь .
Jeremy S

4
@ Джереми: Почему бы и нет ?: println («Вы прошли» + singularPlural (количество, «викторина», «викторины») + «до сих пор»)
Лоуренс Дол

Я мог бы интерпретировать вопрос по-другому. Я думаю, что алгоритм должен определять форму множественного числа без каких-либо подсказок со стороны разработчика, в то время как ваш метод возлагает бремя знания того, что такое множественное число, на разработчика.
Jeremy S

3
@Jeremy: Следовательно, вводная фраза «Я обманул ...», похоже, не оправдывает отрицательного голоса.
Лоуренс Дол

1
Согласовано. Я также считаю, что предоставленная информация была полезной, поэтому я не голосовал против. В общем, я не голосую против «мусора одного человека ...».
Джереми С.

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 ("{She} {is} going to {her | их соответствующий} {home}.", 5)
Jay Querido

Шон Уилсон - Мой компьютер в настоящее время разобран. Я спешу восстановить его и обновлю в течение дня или двух. А пока nuget.org/packages?q=pluralizer
Джей Керидо,

8

Я собрал один из них на основе плюрализатора Rails. Вы можете увидеть мою запись в блоге здесь или на github здесь

output = Formatting.Pluralization(100, "sausage"); 

3
Спасибо, что поделился. Рад, что мне не нужно было ссылаться на другую сборку.
hofnarwillie

1
Просто и красиво !, но в нем отсутствует функциональность Singularize
amd

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

У Subsonic 3 есть Inflectorкласс, который меня впечатлил, превратив Personв People. Я заглянул в источник и обнаружил, что он, естественно, немного обманывает с жестко запрограммированным списком, но это действительно единственный способ сделать это на английском языке и как это делают люди - мы помним единственное и множественное число каждого слова, а не просто применяем правило . Поскольку здесь нет мужского / женского (/ нейтрального), чтобы добавить к смеси, это намного проще.

Вот отрывок:

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- это фактическиInflector класс Castle ActiveRecord !


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"));

Singularize не объединяет «Order_Details» в единое целое. Он возвращает «Order_Details» с точкой sв конце. Что нужно делать?


1
Это вопрос, а не ответ на вопрос ... но Pluralize () и Singularize () работают только со словарными словами. Есть способ добавлять слова с помощью ICustomPluralizationMapping.AddWord, но, по крайней мере, для меня это было не очень хорошее решение, когда у вас может быть много нереальных слов, таких как кодовые имена.
tordal

@tordal Спасибо, это именно то, ради чего я пришел к этому вопросу
Чад
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.