Skip to content

Instantly share code, notes, and snippets.

@chrissie1
Last active August 29, 2015 14:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrissie1/7273a10f7681da7e5b26 to your computer and use it in GitHub Desktop.
Save chrissie1/7273a10f7681da7e5b26 to your computer and use it in GitHub Desktop.
fun String.pluralize() : String{
val rules = listOf(
"$" to "s",
"s$"to "s",
"(ax|test)is$" to "$1es",
"us$" to "i",
"(octop|vir)us$" to "$1i",
"(octop|vir)i$" to "$1i",
"(alias|status)$" to "$1es",
"(bu)s$" to "$1ses",
"(buffal|tomat)o$" to "$1oes",
"([ti])um$" to "$1a",
"([ti])a$" to "$1a",
"sis$" to "ses",
"(,:([^f])fe|([lr])f)$" to "$1$2ves",
"(hive)$" to "$1s",
"([^aeiouy]|qu)y$" to "$1ies",
"(x|ch|ss|sh)$" to "$1es",
"(matr|vert|ind)ix|ex$" to "$1ices",
"([m|l])ouse$" to "$1ice",
"([m|l])ice$" to "$1ice",
"^(ox)$" to "$1en",
"(quiz)$" to "$1zes",
"f$" to "ves",
"fe$" to "ves")
val unCountable = listOf("equipment", "information", "rice", "money",
"species", "series", "fish", "sheep", "aircraft","bison", "flounder", "pliers", "bream",
"gallows", "proceedings", "breeches", "graffiti", "rabies",
"britches", "headquarters", "salmon", "carp", "herpes",
"scissors", "chassis", "high-jinks", "sea-bass", "clippers",
"homework", "cod", "innings", "shears",
"contretemps", "jackanapes", "corps", "mackerel",
"swine", "debris", "measles", "trout", "diabetes", "mews",
"tuna", "djinn", "mumps", "whiting", "eland", "news",
"wildebeest", "elk", "pincers", "sugar")
val exceptions = listOf("person" to "people",
"man" to "men",
"goose" to "geese",
"child" to "children",
"sex" to "sexes",
"move" to "moves",
"stadium" to "stadiums",
"deer" to "deer")
if(unCountable.contains(this)) return this
val rule = rules.last { Pattern.compile(it.component1(), Pattern.CASE_INSENSITIVE).matcher(this).find()}
var found = Pattern.compile(rule.component1(), Pattern.CASE_INSENSITIVE).matcher(this).replaceAll(rule.component2())
val excep = exceptions.firstOrNull() { this.equals(it.component1())}
if(excep !=null) found = excep.component2()
val endswith = exceptions.firstOrNull { this.endsWith(it.component1())}
if(endswith != null) found = this.replace(endswith.component1(),endswith.component2())
return found
}
package org.humanizer.jvm.tests
import org.spek.Spek
import org.spek.givenData
import org.humanizer.jvm.titleize
import org.spek.shouldEqual
import org.humanizer.jvm.pluralize
import org.humanizer.jvm.singularize
public class PluralizeTests() : Spek() {
{
var data = listOf(
"search" to "searches",
"switch" to "switches",
"fix" to "fixes",
"box" to "boxes",
"process" to "processes",
"address" to "addresses",
"case" to "cases",
"stack" to "stacks",
"wish" to "wishes",
"fish" to "fish",
"category" to "categories",
"query" to "queries",
"ability" to "abilities",
"agency" to "agencies",
"movie" to "movies",
"archive" to "archives",
"index" to "indices",
"wife" to "wives",
"safe" to "saves",
"half" to "halves",
"move" to "moves",
"salesperson" to "salespeople",
"person" to "people",
"spokesman" to "spokesmen",
"man" to "men",
"woman" to "women",
"basis" to "bases",
"diagnosis" to "diagnoses",
"datum" to "data",
"medium" to "media",
"analysis" to "analyses",
"node_child" to "node_children",
"child" to "children",
"experience" to "experiences",
"day" to "days",
"comment" to "comments",
"foobar" to "foobars",
"newsletter" to "newsletters",
"old_news" to "old_news",
"news" to "news",
"series" to "series",
"species" to "species",
"quiz" to "quizzes",
"perspective" to "perspectives",
"ox" to "oxen",
"photo" to "photos",
"buffalo" to "buffaloes",
"tomato" to "tomatoes",
"dwarf" to "dwarves",
"elf" to "elves",
"information" to "information",
"equipment" to "equipment",
"bus" to "buses",
"status" to "statuses",
"status_code" to "status_codes",
"mouse" to "mice",
"louse" to "lice",
"house" to "houses",
"octopus" to "octopi",
"virus" to "viri",
"alias" to "aliases",
"portfolio" to "portfolios",
"vertex" to "vertices",
"matrix" to "matrices",
"axis" to "axes",
"testis" to "testes",
"crisis" to "crises",
"rice" to "rice",
"shoe" to "shoes",
"horse" to "horses",
"prize" to "prizes",
"edge" to "edges",
"deer" to "deer",
"sheep" to "sheep",
"wolf" to "wolves"
)
givenData(data) {
val (value, expected) = it
on("calling pluralize on String", {
val actual = value.pluralize()
it("should be ${expected}", {
shouldEqual(expected, actual)
})
})
}
/*givenData(data) {
val (expected, value) = it
on("calling singularize on String", {
val actual = value.singularize()
it("should be ${expected}", {
shouldEqual(expected, actual)
})
})
}*/
}
}
@chrissie1
Copy link
Author

I'm getting an NRE ( actually java.lang.IllegalArgumentException: No element matching predicate was found) on the .component2() line when this is not in the exceptions list. I thought you didn't have that in kotlin. Better way?

@hhariri
Copy link

hhariri commented May 6, 2014

Give me full context. What's this? Also you've got found defined twice.

@chrissie1
Copy link
Author

I updated the gist with the current code for pluralize, far from complete but it's a start.

"man".pluralize() should give "men" and is one of the exceptions not covered by the regex rules

@hhariri
Copy link

hhariri commented May 6, 2014

you're seeing the compiler hints right?

@hhariri
Copy link

hhariri commented May 6, 2014

Your problem is that first is not finding a matching element. That's what the exception is throwing.

@chrissie1
Copy link
Author

the compiler hints are wrong because when I run the tests I get an error on that line. Added tests.

@chrissie1
Copy link
Author

So maybe I should use some other method?

@hhariri
Copy link

hhariri commented May 6, 2014

Compiler hints aren't wrong. You're assigning a value to found, not using it. Then assigning a new value, not using it, then assigning another value, not using it.

@chrissie1
Copy link
Author

you are saying I'm wrong. The nerve.

@chrissie1
Copy link
Author

Ok I was wrong, the last version is now there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment