У ImprovedNamingStrategy есть метод addUnderscores (), который вызывается из tableName () и columnName (), вы можете реализовать свой собственный класс стратегии именования и переопределить их согласно вашему выбору
public class MyOwnNamingStrategy extends ImprovedNamingStrategy {
@Override
public String tableName(String tableName) {
//return addUnderscores(columnName); // skip this
return columnName; // if you want column name variable name same
//return changeAsYouWant(columnName); // as name sames
}
}
Я думаю, что у вас уже есть "лучшее" решение.
Если вы хотите продемонстрировать больше функциональных/F#-измов, вы можете сделать, например,
[1..100]
|> Seq.map (function
| x when x%5=0 && x%3=0 -> "FizzBuzz"
| x when x%3=0 -> "Fizz"
| x when x%5=0 -> "Buzz"
| x -> string x)
|> Seq.iter (printfn "%s")
и использовать списки, последовательности, map, iter, паттерны и частичное применение.
[1..100] // I am the list of numbers 1-100.
// F# has immutable singly-linked lists.
// List literals use square brackets.
|> // I am the pipeline operator.
// "x |> f" is just another way to write "f x".
// It is a common idiom to "pipe" data through
// a bunch of transformative functions.
Seq.map // "Seq" means "sequence", in F# such sequences
// are just another name for IEnumerable<T>.
// "map" is a function in the "Seq" module that
// applies a function to every element of a
// sequence, returning a new sequence of results.
(function // The function keyword is one way to
// write a lambda, it means the same
// thing as "fun z -> match z with".
// "fun" starts a lambda.
// "match expr with" starts a pattern
// match, that then has |cases.
| x when x%5=0 && x%3=0
// I'm a pattern. The pattern is "x", which is
// just an identifier pattern that matches any
// value and binds the name (x) to that value.
// The "when" clause is a guard - the pattern
// will only match if the guard predicate is true.
-> "FizzBuzz"
// After each pattern is "-> expr" which is
// the thing evaluated if the pattern matches.
// If this pattern matches, we return that
// string literal "FizzBuzz".
| x when x%3=0 -> "Fizz"
// Patterns are evaluated in order, just like
// if...elif...elif...else, which is why we did
// the 'divisble-by-both' check first.
| x when x%5=0 -> "Buzz"
| x -> string x)
// "string" is a function that converts its argument
// to a string. F# is statically-typed, so all the
// patterns have to evaluate to the same type, so the
// return value of the map call can be e.g. an
// IEnumerable<string> (aka seq<string>).
|> // Another pipeline; pipe the prior sequence into...
Seq.iter // iter applies a function to every element of a
// sequence, but the function should return "unit"
// (like "void"), and iter itself returns unit.
// Whereas sequences are lazy, "iter" will "force"
// the sequence since it needs to apply the function
// to each element only for its effects.
(printfn "%s")
// F# has type-safe printing; printfn "%s" expr
// requires expr to have type string. Usual kind of
// %d for integers, etc. Here we have partially
// applied printfn, it's a function still expecting
// the string, so this is a one-argument function
// that is appropriate to hand to iter. Hurrah!
Чтобы добавить еще один возможный ответ - вот еще один подход без сопоставления с образцом. Он использует тот факт, что Fizz + Buzz = FizzBuzz
, поэтому вам не нужно проверять все три случая, вам нужно только посмотреть, делится ли оно на 3 (затем вывести «Fizz»), а также посмотреть, делится ли оно на 5 (затем выведите «Buzz») и, наконец, выведите новую строку:
for i in 1..100 do
for divisor, str in [ (3, "Fizz"); (5; "Buzz") ] do
if i % divisor = 0 then printf str
printfn ""
Вложенный цикл for
присваивает 3 и «Fizz» значение divisor
и str
в первой итерации, а затем вторая пара значений во второй итерации. Преимущество заключается в том, что вы можете легко добавить печать "Jezz", когда значение делится на 7 :-) ... в случае, если проблема заключается в расширяемости решения!
Вот моя версия:
//initialize array a with values from 1 to 100
let a = Array.init 100 (fun x -> x + 1)
//iterate over array and match *indexes* x
Array.iter (fun x ->
match x with
| _ when x % 15 = 0 -> printfn "FizzBuzz"
| _ when x % 5 = 0 -> printfn "Buzz"
| _ when x % 3 = 0 -> printfn "Fizz"
| _ -> printfn "%d" x
) a
Это моя первая программа на F #.
Это не идеально, но я думаю, что тот, кто начинает изучать F # (как я :)), может понять, что здесь происходит довольно быстро.
Однако мне интересно, в чем разница между соответствием любому _
или самому x
в сопоставлении с образцом выше?
Я не смог найти работающее решение, которое не включало бы тестирование для i% 15 = 0 . Я всегда чувствовал, что не тестирование для этого является частью этого "глупого" задания. Имейте в виду, что это, вероятно, не идиоматический F #, так как это моя первая программа на языке.
for n in 1..100 do
let s = seq {
if n % 3 = 0 then yield "Fizz"
if n % 5 = 0 then yield "Buzz" }
if Seq.isEmpty s then printf "%d"n
printfn "%s"(s |> String.concat "")
Мне не нравятся все эти повторяющиеся строки, вот моя:
open System
let ar = [| "Fizz"; "Buzz"; |]
[1..100] |> List.map (fun i ->
match i % 3 = 0, i % 5 = 0 with
| true, false -> ar.[0]
| false, true -> ar.[1]
| true, true -> ar |> String.Concat
| _ -> string i
|> printf "%s\n"
)
|> ignore
Еще одно решение в стиле F # (т.е. с использованием активных шаблонов):
let (|P3|_|) i = if i % 3 = 0 then Some i else None
let (|P5|_|) i = if i % 5 = 0 then Some i else None
let f = function
| P3 _ & P5 _ -> printfn "FizzBuzz"
| P3 _ -> printfn "Fizz"
| P5 _ -> printfn "Buzz"
| x -> printfn "%d" x
Seq.iter f {1..100}
//or
for i in 1..100 do f i
Мой пример - лишь незначительное улучшение по сравнению с кодом, опубликованным ssp. Он использует параметризованные активные шаблоны (которые принимают делитель в качестве аргумента). Вот более подробное объяснение:
Следующее определяет активный шаблон , который мы позже можем использовать в выражении match
, чтобы проверить, имеет ли значение i
делится на значение делитель
. Когда мы пишем:
match 9 with
| DivisibleBy 3 -> ...
... это означает, что значение «9» будет передано следующей функции как i
, а значение 3
будет передано как делитель
. Имя (| DivisibleBy | _ |)
- это специальный синтаксис, означающий, что мы объявляем активный шаблон (и имя может появиться в совпадении
в левой части ->
.Бит | _ |
означает, что шаблон может завершиться ошибкой (наш пример терпит неудачу, когда значение не делится на делитель
)
let (|DivisibleBy|_|) divisor i =
// If the value is divisible, then we return 'Some()' which
// represents that the active pattern succeeds - the '()' notation
// means that we don't return any value from the pattern (if we
// returned for example 'Some(i/divisor)' the use would be:
// match 6 with
// | DivisibleBy 3 res -> .. (res would be asigned value 2)
// None means that pattern failed and that the next clause should
// be tried (by the match expression)
if i % divisor = 0 then Some () else None
Теперь мы можем перебрать все числа и сопоставить их шаблоны (наш активный шаблон) с использованием match
(или с использованием Seq.iter
или какой-либо другой техники, как показано в других ответах):
for i in 1..100 do
match i with
// & allows us to run more than one pattern on the argument 'i'
// so this calls 'DivisibleBy 3 i' and 'DivisibleBy 5 i' and it
// succeeds (and runs the body) only if both of them return 'Some()'
| DivisibleBy 3 & DivisibleBy 5 -> printfn "FizzBuzz"
| DivisibleBy 3 -> printfn "Fizz"
| DivisibleBy 5 -> printfn "Buzz"
| _ -> printfn "%d" i
Для получения дополнительной информации об активных шаблонах F #, вот ссылка на документацию MSDN . Думаю, если убрать все комментарии, код будет чуть читабельнее, чем исходная версия. Здесь показаны довольно полезные приемы :-), но в вашем случае задача относительно проста ...