Нарезка подобной функциональности из списка в F #

StackOverflow https://stackoverflow.com/questions/1984416

  •  22-09-2019
  •  | 
  •  

Вопрос

С массивом let foo = [|1;2;3;4|] Я могу использовать любое из следующих действий, чтобы вернуть фрагмент массива.

foo.[..2] 
foo.[1..2] 
foo.[2..]

Как я могу сделать то же самое для списка let foo2 = [1;2;3;4]?Когда я пробую тот же синтаксис, что и массив, я получаю error FS00039: The field, constructor or member 'GetSlice' is not defined.

Какой метод получения подраздела списка является предпочтительным и почему они не поддерживают GetSlice?

Это было полезно?

Решение

Каков предпочтительный метод получения подраздела списка и почему не создается для поддержки Getslice?

Давайте сделаем последний вопрос первым, а первый вопрос последним:

Почему списки не поддерживают GetSlice

Списки реализованы как связанные списки, поэтому у нас нет эффективного индексированного доступа к ним.Сравнительно говоря, foo.[|m..n|] берет O(n-m) время для массивов, эквивалентный синтаксис занимает O(n) время в списках.Это довольно большая проблема, поскольку она не позволяет нам эффективно использовать синтаксис срезов в подавляющем большинстве случаев, когда он был бы полезен.

Например, мы можем разрезать массив на части одинакового размера за линейное время:

let foo = [|1 .. 100|]
let size = 4
let fuz = [|for a in 0 .. size .. 100 do yield foo.[a..a+size] |]

Но что, если вместо этого мы будем использовать список?Каждый звонок в foo.[a..a+size] займет все больше и больше времени, вся операция O(n^2), что делает его совершенно непригодным для работы.

В большинстве случаев нарезка списка — неправильный подход.Обычно мы используем сопоставление с образцом для перемещения по спискам и управления ими.

Предпочитаемый метод разрезания списка?

По возможности используйте сопоставление с образцом.В противном случае вы можете вернуться к Seq.skip и Seq.take чтобы разрезать для вас списки и последовательности:

> [1 .. 10] |> Seq.skip 3 |> Seq.take 5 |> Seq.toList;;
val it : int list = [4; 5; 6; 7; 8]

Другие советы

F# 4.0 позволит нарезать синтаксис для списков (связь).

Обоснование здесь:

Тип списка F# уже поддерживает оператор индекса xs.[3].Это сделано несмотря на то, что списки в F# являются связанными списками — списки настолько часто используются в F#, что в F# 2.0 было решено поддержать это.

Поскольку поддерживается синтаксис индекса, имеет смысл также поддерживать синтаксис срезов F#, напримерхз.[3..5].Очень странно переключаться на тип массива, чтобы использовать срезы, но вам не обязательно делать это для индексации.

Тем не менее, ответ Джульетты о том, что в большинстве случаев нарезка списка является неправильным подходом, по-прежнему остается верным.Так что будьте мудры при использовании этой функции.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top