Existe algum algoritmo em c # para singularizar - pluralizar uma palavra?

106

Existe algum algoritmo em c # para singularizar - pluralizar uma palavra (em inglês) ou existe uma biblioteca .net para fazer isso (também pode estar em diferentes idiomas)?

Ronnie
fonte

Respostas:

182

Você também tem System.Data.Entity.Design.PluralizationServices.PluralizationService .

ATUALIZAÇÃO : a resposta antiga merece atualização. Agora também existe o Humanizer: https://github.com/MehdiK/Humanizer

Daniel
fonte
2
Hmmm, você tem permissão para redistribuir ou apenas usar uma DLL de design? Eu pergunto porque sei que a licença do DevExpress proíbe a redistribuição de qualquer DLL .design.
Pierre-Alain Vigeant
58
Abrir o código com ILSpy mostra uma classe chamada EnglishPluralizationService, que tem muitos casos excepcionais definidos em e torna a leitura interessante. Eu particularmente gosto de 'pneumonoultramicroscopicsilicovolcanoconiose', que eu uso o tempo todo em meus modelos de entidade ... 8o)
MrKWatkins
7
Eu posso adivinhar como isso foi adicionado. Um testador registrou um bug no dev dizendo que ele não funciona para a palavra dita. Dev consertou. Ambos compartilharam uma risada.
merlinbeard
2
@MrKWatkins Soa mais como 'supercalifragilisticexpialidocious'
Corstian Boerman,
1
Humanizer é uma ótima recomendação. É claro que eu mesmo implementei 15% antes de descobrir que existia.
Casey
18

Posso fazer pelo Esperanto, sem casos especiais!

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

Para o inglês, seria útil se familiarizar com as regras para Plurais regulares de substantivos , bem como Plurais irregulares de substantivos . Há todo um artigo da Wikipedia no plural inglês , que também pode conter algumas informações úteis.

Greg Hewgill
fonte
5
Você deve fazê-lo lançar se passar um verbo ou advérbio!
Timwi,
1
@Matt: Claro que isso é apropriado para o caso nominativo; Acredito que estender esse método ao caso acusativo seja direto para um leitor astuto.
Greg Hewgill
14

A maioria dos ORMs tenta fazer isso, embora geralmente não sejam perfeitos. Eu sei que Castle tem sua classe inflector, você provavelmente pode dar uma olhada. No entanto, fazê-lo "perfeitamente" não é uma tarefa fácil ("regras" em inglês não são realmente regras :)), então depende se você está satisfeito com uma abordagem de "palpite razoável".

Steven Robbins
fonte
De acordo com sua sugestão, pesquisei "Inflector" e encontrei este andrewpeters.net/inflectornet que deve ser basicamente o mesmo do Castle
Ronnie
4
Na verdade, não é basicamente o mesmo, é idêntico.
David Pfeffer
12

Eu trapaceei em Java - queria ser capaz de produzir uma string correta para "Houve n algo (s)", então escrevi o seguinte. método utilitário pouco sobrecarregado:

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

invocado assim

System.out.println("There were "+pluralize(count,"something"));
System.out.println("You have broken "+pluralize(count,"knife","knives"));
Lawrence Dol
fonte
No entanto, isso cobre apenas pequenas seções de gramática, não leva em consideração palavras como questionários, festas, metades, ratos, índices, etc. É uma boa tentativa inicial, mas há muitas outras regras que provavelmente devem ser processadas primeiro .
Jeremy S
4
@Jeremy: Por que não ?: println ("Você passou" + singularPlural (contagem, "questionário", "questionários") + "até agora")
Lawrence Dol
Eu posso estar interpretando a pergunta de forma diferente. Estou pensando que o algoritmo deve determinar a forma plural sem qualquer dica do desenvolvedor, enquanto seu método coloca o ônus de saber qual é a forma plural no desenvolvedor.
Jeremy S
3
@Jeremy: Conseqüentemente, a sugestão de "Eu trapaceei ..." não parece justificar um voto negativo.
Lawrence Dol
1
Acordado. Eu também acho que a informação fornecida foi útil, por isso nenhum downvote veio de mim. Eu não voto negativo em geral, na linha do "lixo de um homem ...".
Jeremy S de
10

Eu criei uma pequena biblioteca para isso em .net (C #), chamada Pluralizer (sem surpresa).

Ele deve funcionar com frases completas, algo como String.Format.

Basicamente, funciona assim:

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

Também pode fazer muito mais do que isso. Leia mais sobre isso no meu blog . Também está disponível no NuGet.

Jay Querido
fonte
4
Sim, essa biblioteca contém apenas palavras simples e apenas substantivos (embora o Pluralizer use essa classe internamente). Esta biblioteca torna mais fácil escrever frases inteiras. Dê uma olhada no meu blog para mais exemplos. Pluralizer.Instance.Pluralize ("{She} {is} going to {her | their respectives} {home}.", 5)
Jay Querido
Shaun Wilson - Meu computador está atualmente em partes. Estou com pressa para recuperá-lo e atualizarei em um ou dois dias. Nesse meio tempo, nuget.org/packages?q=pluralizer
Jay Querido
8

Eu bati um junto com base no pluralizador Rails. Você pode ver minha postagem do blog aqui , ou no github aqui

output = Formatting.Pluralization(100, "sausage"); 
Matt Grande
fonte
3
Obrigado por compartilhar. Ainda bem que não precisei fazer referência a outra montagem.
hofnarwillie
1
Simples e bonito !, mas falta a funcionalidade Singularize
amd
5

Como a pergunta era para C #, aqui está uma boa variação da solução do Software Monkey (novamente um pouco "cheat", mas para mim realmente a maneira mais prática e reutilizável de fazer isso):

    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;
    }

O uso é o seguinte:

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

"Person".Pluralize(1, "People") = "Person"
"Person".Pluralize(2, "People") = "People"
Zaid Masud
fonte
3

Subsonic 3 tem uma Inflectorclasse que me impressionou ao se PersontornarPeople . Eu dei uma olhada na fonte e descobri que naturalmente trapaceia um pouco com uma lista codificada, mas essa é realmente a única maneira de fazer isso em inglês e como os humanos fazem isso - lembramos do singular e do plural de cada palavra e não apenas aplicamos uma regra . Como não há masculino / feminino (/ neutro) para adicionar à mistura, é muito mais simples.

Aqui está um snippet:

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

É responsável por algumas palavras que não possuem equivalentes no plural, como o exemplo do equipamento. Como você provavelmente pode dizer, ele faz um simplesRegex substituição usando $ 1.

Atualização:
Parece que Subsonic Inflectoré de fato a classe Castle ActiveRecordInflector !

Chris S
fonte
2

Não há muita documentação do MSDN sobre o uso específico da classe PluralizationService, então aqui está uma classe de teste de unidade (NUnit) para mostrar o uso básico. Observe o caso de teste estranho na parte inferior que mostra que o serviço não é perfeito quando se trata de formas plurais não padronizadas.

[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
    }
}
Ryan Rodemoyer
fonte
1

Usando o banco de dados de exemplo Northwind da Microsoft:

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

Singularize não Singularize "Order_Details" Ele retorna "Order_Details" com sno final. Qual é a solução?

RandallTo
fonte
1
Esta é uma pergunta, não uma resposta a uma pergunta ... mas Pluralize () e Singularize () só funcionam com palavras do dicionário. Existe uma maneira de adicionar palavras usando ICustomPluralizationMapping.AddWord, mas pelo menos para mim, essa não foi uma solução muito boa quando você pode ter muitas palavras não reais, como nomes de código.
tordal
@tordal Obrigado, é exatamente para isso que cheguei a esta pergunta
Chad