#c# #f# #youtube
#c# #f# #YouTube
Вопрос:
Я пытаюсь использовать Youtube .Net API в F # и я столкнулся с проблемой, пытаясь получить доступ к IEnumerable, возвращенному в userPlaylists.Свойство записей. Ниже приведен код c #, который я тестировал, однако, похоже, я не могу вернуть отдельные элементы из коллекции IEnumerable в f #.
Feed<Playlist> userPlaylists = request.GetPlaylistsFeed("username");
var p = userPlaylists.Entries.Single<Playlist>(x => x.Title == "playlistname");
Записи преобразуются в тип IEnumerable<Playlist> Feed<PlayList>.Entries
IEnumerable, похоже, представлен в виде последовательности в F #, но, похоже, я не могу понять, как вернуть и отдельный элемент правильного типа, ближайший, который я получил, был:
let UserPlaylists = Request.GetPlaylistsFeed("username")
let pl = UserPlaylists.Entries |>
Seq.tryPick(fun x -> if x.Title="playlistname" then Some(x) else None)
Однако это, похоже, возвращает тип «Опции списка воспроизведения» вместо «Списка воспроизведения». Кто-нибудь может предложить правильный способ извлечения отдельного элемента из IEnumerable?
Комментарии:
1. Что вы хотите сделать, если нужный элемент не найден в seq?
Ответ №1:
Метод расширения Single() выдает исключение, если не находит совпадения, и он также выдает исключение, если находит более одного совпадения. В модуле F # Seq
нет прямого эквивалента. Самым близким было бы то, Seq.find
что like .Single()
выдаст исключение, если не найдет совпадения, однако в отличие от .Single()
этого, он прекратит поиск, как только найдет совпадение, и не выдаст ошибку, если существует более одного совпадения.
Если вам действительно нужно поведение «выдавать ошибку при более чем одном совпадении», то проще всего было бы использовать именно этот метод из F#:
open System.Linq
let p = userPlaylists.Entries.Single(fun x -> x.Title = "playlistname")
Если вам не нужно поведение «throw if more than one match», то вам также не следует использовать .Single()
в вашем коде C # — .First()
будет работать лучше, потому что он прекращает поиск, как только находит совпадение.
На моем месте я бы для краткости использовал use Seq.tryFind
over Seq.tryPick
и обработал случай «не найден», а не выдавал ошибку.
let userPlaylists = request.GetPlaylistsFeed("username")
let p = userPlaylists.Entries |> Seq.tryFind (fun x -> x.Title = "playlistname")
match p with
| Some pl ->
// do something with the list
| None ->
// do something else because we didn't find the list
Или, альтернативно, я мог бы сделать это без создания промежуточных значений, на которые ссылаются только один раз…
request.GetPlaylistsFeed("username").Entries
|> Seq.tryFind (fun x -> x.Title = "playlistname")
|> function
| Some pl ->
// do something with the list
| None ->
// do something else because we didn't find the list
Мне действительно нравится оператор конвейера…
Ответ №2:
Seq.tryPick
сродни IEnumerable.FirstOrDefault
последующему преобразованию типа, которое не имеет семантики, которую вы ищете. Seq.pick
похоже на IEnumerable.First
последующее преобразование типа, которое является шагом в правильном направлении (предполагая, что вы хотите, чтобы исключение выдавалось при невозможности найти какой-либо соответствующий элемент, как с IEnumerable.Single
), но поскольку вам на самом деле не нужно преобразование типа, я думаю, что вы действительно хотите Seq.find
, которое семантически идентично IEnumerable.First
:
let UserPlaylists = Request.GetPlaylistsFeed "username"
let pl = UserPlaylists.Entries |> Seq.find (fun x -> x.Title = "playlistname")
Тем не менее, если вам действительно нужна семантика IEnumerable.Single
, а не IEnumerable.First
, проигнорируйте это и посмотрите ответ @JoelMueller .
Ответ №3:
Используйте Option.get
метод, чтобы получить значение из параметра
Seq.tryPick(fun x -> if x.Title="playlistname" then Some(x) else None)
|> Option.get
Хотя в F # я считаю, что более идиоматично явно обрабатывать пустой регистр вместо использования распространения исключения
let value = Seq.tryPick(fun x -> if x.Title="playlistname" then Some(x) else None)
match value with
| None ->
// No matching elements. Take corrective action
| Some value ->
// The value i'm looking for