Решение на Code Identifier от Антонио Миндов

Обратно към всички решения

Към профила на Антонио Миндов

Резултати

  • 20 точки от тестове
  • 0 бонус точки
  • 20 точки общо
  • 15 успешни тест(а)
  • 0 неуспешни тест(а)

Код

/// Необходимо е CodeIdentifier да имплементира Debug, за да можем да го
/// използваме в тестови assertion-и.
///
#[derive(Debug)]
pub struct CodeIdentifier {
identifier: String
}
impl CodeIdentifier {
fn is_valid(identifier: &str) -> bool {
match identifier.chars().next() {
Some(c) => if !c.is_alphabetic() { return false }
_ => return false
}
identifier.chars().all(|c| c.is_alphanumeric() || c == '_')
}
fn capitalize(s: &str) -> String {
let mut chars = s.chars();
match chars.next() {
Some(c) => c.to_uppercase().chain(chars).collect(),
None => String::new()
}

Чудесна употреба на chain, готино се е получил кода :). Случая с None е малко досаден, понеже проверката за празен низ си я направил горе -- със сигурност ще има поне един символ, така че няма "добър" начин да имплементираш None клона.

В идеалния случай, няма да се стига до такъв код, но зависи как се структурира -- има валидни начини да се окажеш в ситуация, в която единия клон не би трябвало да може да се стигне. Може да сложиш на мястото на String::new() макроса unreachable!(), който ще гръмне, ако някога се удари този клон при програмистка грешка. За предпочитане е това, пред връщането на празен низ без обяснение защо така е станало.

Уф, всъщност не, сори. Изглежда съм претупал малко review-то днес, и не съм видял, че ти си връщаш резултата като output. Нямам идея какво съм си мислел със съвета, напълно разумно е да върнеш String::new(). Но пък хей, поне те научих за макроса unreachable!() :).

}
/// Функцията ще върне Option<CodeIdentifier>, което ще бъде:
/// - None: ако входа не е валиден идентификатор. Вижте горе за това
/// какво значи "валиден идентификатор".
/// - Some(code_identifier): Ако входа е валиден.
///
pub fn new(identifier: &str) -> Option<Self> {
let trimmed = identifier.trim();
if CodeIdentifier::is_valid(trimmed) {
Some(CodeIdentifier{identifier: String::from(trimmed.to_lowercase())})
} else {
None
}
}
/// Конвертира идентификатора до camelcased вариант.
/// - Примерен вход: "some_var"
/// - Примерен изход: "someVar"
///
pub fn camelcase(&self) -> String {
let mut split_it = self.identifier.split('_');
if let Some(first) = split_it.next() {
let mut first_str = first.to_string();
split_it.map(CodeIdentifier::capitalize).for_each(|x| first_str.push_str(&x));
return first_str
}
String::new()
}
/// Конвертира идентификатора до titlecased вариант (camelcased с първа заглавна буква).
/// - Примерен вход: "some_var"
/// - Примерен изход: "SomeVar"
///
pub fn titlecase(&self) -> String {
match self.camelcase().get(..) {
Some(camelcase) => CodeIdentifier::capitalize(camelcase),
None => String::new()
}
}
/// Конвертира идентификатора до kebabcased вариант.
/// - Примерен вход: "some_var"
/// - Примерен изход: "some-var"
///
pub fn kebabcase(&self) -> String {
self.identifier.replace("_", "-")
}
/// Конвертира идентификатора до underscored вариант.
/// - Примерен вход: "some_var"
/// - Примерен изход: "some_var"
///
/// - Примерен вход: "Some_Var"
/// - Примерен изход: "some_var"
///
pub fn underscore(&self) -> String {
self.identifier.clone()
}
/// Конвертира идентификатора до screaming-snakecased вариант.
/// - Примерен вход: "some_var"
/// - Примерен изход: "SOME_VAR"
///
pub fn screaming_snakecase(&self) -> String {
self.identifier.to_uppercase()
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20190123-22631-qp9un7/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 5.21s
     Running target/debug/deps/solution-2e785d603b538f71

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-29808948fb50ed3a

running 15 tests
test solution_test::test_both_static_and_dynamic_strings ... ok
test solution_test::test_camelcase_basic ... ok
test solution_test::test_cyrillic1 ... ok
test solution_test::test_digits1 ... ok
test solution_test::test_digits2 ... ok
test solution_test::test_digits3 ... ok
test solution_test::test_kebabcase_basic ... ok
test solution_test::test_multibyte_uppercase ... ok
test solution_test::test_normalize_case1 ... ok
test solution_test::test_normalize_case2 ... ok
test solution_test::test_screaming_snakecase_basic ... ok
test solution_test::test_titlecase_basic ... ok
test solution_test::test_underscore_basic ... ok
test solution_test::test_validity ... ok
test solution_test::test_whitespace ... ok

test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

История (2 версии и 3 коментара)

Антонио качи първо решение на 20.10.2018 10:32 (преди почти 7 години)

Антонио качи решение на 20.10.2018 10:57 (преди почти 7 години)

/// Необходимо е CodeIdentifier да имплементира Debug, за да можем да го
/// използваме в тестови assertion-и.
///
#[derive(Debug)]
pub struct CodeIdentifier {
identifier: String
}
impl CodeIdentifier {
fn is_valid(identifier: &str) -> bool {
match identifier.chars().next() {
Some(c) => if !c.is_alphabetic() { return false }
_ => return false
}
identifier.chars().all(|c| c.is_alphanumeric() || c == '_')
}
fn capitalize(s: &str) -> String {
let mut chars = s.chars();
match chars.next() {
Some(c) => c.to_uppercase().chain(chars).collect(),
None => String::new()
}

Чудесна употреба на chain, готино се е получил кода :). Случая с None е малко досаден, понеже проверката за празен низ си я направил горе -- със сигурност ще има поне един символ, така че няма "добър" начин да имплементираш None клона.

В идеалния случай, няма да се стига до такъв код, но зависи как се структурира -- има валидни начини да се окажеш в ситуация, в която единия клон не би трябвало да може да се стигне. Може да сложиш на мястото на String::new() макроса unreachable!(), който ще гръмне, ако някога се удари този клон при програмистка грешка. За предпочитане е това, пред връщането на празен низ без обяснение защо така е станало.

Уф, всъщност не, сори. Изглежда съм претупал малко review-то днес, и не съм видял, че ти си връщаш резултата като output. Нямам идея какво съм си мислел със съвета, напълно разумно е да върнеш String::new(). Но пък хей, поне те научих за макроса unreachable!() :).

}
- fn capitalizeS(s: &String) -> String {
- let mut chars = s.chars();
- match chars.next() {
- Some(c) => c.to_uppercase().chain(chars).collect(),
- None => String::new()
- }
- }
-
/// Функцията ще върне Option<CodeIdentifier>, което ще бъде:
/// - None: ако входа не е валиден идентификатор. Вижте горе за това
/// какво значи "валиден идентификатор".
/// - Some(code_identifier): Ако входа е валиден.
///
pub fn new(identifier: &str) -> Option<Self> {
let trimmed = identifier.trim();
if CodeIdentifier::is_valid(trimmed) {
Some(CodeIdentifier{identifier: String::from(trimmed.to_lowercase())})
} else {
None
}
}
/// Конвертира идентификатора до camelcased вариант.
/// - Примерен вход: "some_var"
/// - Примерен изход: "someVar"
///
pub fn camelcase(&self) -> String {
let mut split_it = self.identifier.split('_');
if let Some(first) = split_it.next() {
- let mut a =String::from(first);
- let b: Vec<String> = split_it.map(|s| CodeIdentifier::capitalize(s)).collect();
- a.push_str(&b.join(""));
- return a
+ let mut first_str = first.to_string();
+ split_it.map(CodeIdentifier::capitalize).for_each(|x| first_str.push_str(&x));
+ return first_str
}
String::new()
}
/// Конвертира идентификатора до titlecased вариант (camelcased с първа заглавна буква).
/// - Примерен вход: "some_var"
/// - Примерен изход: "SomeVar"
///
pub fn titlecase(&self) -> String {
- CodeIdentifier::capitalizeS(&self.camelcase())
+ match self.camelcase().get(..) {
+ Some(camelcase) => CodeIdentifier::capitalize(camelcase),
+ None => String::new()
+ }
}
/// Конвертира идентификатора до kebabcased вариант.
/// - Примерен вход: "some_var"
/// - Примерен изход: "some-var"
///
pub fn kebabcase(&self) -> String {
self.identifier.replace("_", "-")
}
/// Конвертира идентификатора до underscored вариант.
/// - Примерен вход: "some_var"
/// - Примерен изход: "some_var"
///
/// - Примерен вход: "Some_Var"
/// - Примерен изход: "some_var"
///
pub fn underscore(&self) -> String {
self.identifier.clone()
}
/// Конвертира идентификатора до screaming-snakecased вариант.
/// - Примерен вход: "some_var"
/// - Примерен изход: "SOME_VAR"
///
pub fn screaming_snakecase(&self) -> String {
self.identifier.to_uppercase()
}
}