Должен ли я прочитать файл в массиве/список, а оттуда выбрать лучшие результаты или есть лучше способ выбрать лучшие результаты непосредственно из файла?
Если оценки уже не отсортированы по файлу, вам нужно будет просмотреть их все, чтобы узнать, что такое Top 3. Способ записи вашего файла прямо сейчас, разбор данных обратно может быть немного сложным - баллы хранятся на нескольких строках, поэтому вам придется это обработать.
Предполагая, что файл не должен быть удобным для людей, я бы выбрал вместо него список значений, разделенных запятыми. Человеку труднее читать, открывая файл, но это упрощает анализ в вашей программе .. Например, если линии выглядят Name,Time,Score
, они могут быть разобраны, как это:
type ScoreData = {
Name : string
Time : string // could be a DateTime, using string for simplicity
Score : int
}
let readHighScores file =
File.ReadAllLines file
|> Array.choose (fun line ->
match line.Split ',' with
| [| name; time; score |] ->
{
Name = name
Time = time
Score = (int)score // This will crash if the score isn't an integer - see paragraph below.
}
|> Some
| _ ->
// Line doesn't match the expected format, we'll just drop it
None
)
|> Array.sortBy (fun scoreData -> -scoreData.Score) // Negative score, so that the highest score comes first
|> Seq.take 3
Это будет прочитать файл и вывод из трех крупнейших баллов. Использование Array.choose позволяет сохранять строки только в том формате, который вы ожидаете. Это также позволяет вам добавить дополнительную проверку по мере необходимости, например, чтобы убедиться, что оценка является целым числом и, возможно, разобрав Время в System.DateTime
вместо того, чтобы хранить его как int
.
Вы можете распечатать свои лучшие результаты, делая что-то вроде этого:
let highScores = readHighScores "hiscore.txt"
printfn "High scores:"
highScores
|> Seq.iteri (fun index data ->
printfn "#%i:" (index + 1)
printfn " Name: %s" data.Name
printfn " Time: %s" data.Time
printfn " Score: %i" data.Score
)
Это вызывает ранее определенную функцию и печатает каждый из счетов, возвращенных - топ 3, в этом случае. Используя Seq.iteri
, вы можете включить индекс в результат в дополнение к самим данным оценки. Используя некоторые данные, которые я сделал вверх, он заканчивает тем, как это:
High scores:
#1:
Name: Awots
Time: 2015-06-15
Score: 2300
#2:
Name: Roujo
Time: 2016-03-01
Score: 2200
#3:
Name: Awots
Time: 2016-03-02
Score: 2100
Теперь, может быть способ сделать это без загрузки всего файла сразу в памяти, но я не думаю, что было бы стоит того, если у вас действительно большой файл, и в этом случае вам может потребоваться сортировка или использование более подходящего метода хранения, например базы данных.
Вы можете просто сохранить только 3-е (или, может быть, несколько дополнительных), вместо того, чтобы хранить все высокие баллы. Просто прочитайте весь файл и напишите заменяющий файл с текущими топ-3 баллами. –