F #: Возвращение списка с измененным элементом в индексе - PullRequest
0 голосов
/ 30 апреля 2019

В F # мне нужно получить список из существующего списка со значением по определенному индексу, отличному от исходного.Все, что я могу найти в Google и здесь, относится к изменению чего-либо на основе значения, а не индекса (достаточно справедливо, потому что списки на самом деле не имеют понятия «индекс», но держу пари, что все знали, что я имел в виду).

Это достаточно просто для написания кода.На данный момент у меня есть:

// Replace element at index with newElement in seq. Does nothing if index is outside seq.
let updateElement index newElement seq =
    let rec updateElementHelper seq count result =
        match seq with
        | [] -> result |> List.rev
        | head::tail ->
            if count = index then 
                updateElementHelper [] (count + 1) (newElement::result)@tail
            else
                updateElementHelper tail (count + 1) (head::result)
    updateElementHelper seq 0 []

, который, кажется, работает просто отлично, но есть ли более естественный способ, чем этот?

(F # новичок - или, скорее, отступать после очень долгогосломаться и никогда не продвинуться так далеко в первый раз).

Ответы [ 2 ]

2 голосов
/ 30 апреля 2019

Самый простой способ реализовать это, вероятно, использовать функцию List.mapi - она ​​вызывает функцию, которую вы предоставляете для каждого элемента списка, и дает вам индекс, так что вы можете либо вернуть исходный элемент или ваш новый элемент,в зависимости от индекса:

let updateElement index element list = 
  list |> List.mapi (fun i v -> if i = index then element else v)

updateElement 4 40 [ 0 .. 9 ]

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

1 голос
/ 30 апреля 2019

Я предполагаю, что вы не хотите, чтобы список был изменчивым.Если вы это сделали, то можете просто внести в список индекс и обновить значение, например, mylist.[index] <- newValue.

Я скажу прямо сейчас, что любая операция в списке, которая использует любой другой вид доступа, кроме типичного стиля "голова + хвост -> рекурс на хвосте", является сильным признаком того, что список не является правильнымструктура данных для вашей работы.См., Например, ответ Джульетты здесь. Обычно, если вы хотите работать с линейной структурой данных по индексу, лучше всего использовать массив.

Самый простой способ, который я могу придуматьэто, если вы все еще хотите сделать это со списком, было бы что-то вроде следующего:

let newList = oldList.[..index - 1] @ (newValue :: oldList.[index + 1..])

(возможно, индексы немного смещены)

Вероятно, это будет очень плохопроизводительность, однако.Я думаю, что было бы разумно сказать, что многие F # -меры будут вызывать любое использование @ или List, нарезающих запах кода.В качестве очень редкой операции для небольших списков это может быть хорошо, но если она будет использоваться часто или в больших списках, то было бы неплохо подумать, действительно ли список является подходящей структурой данных сбора для вашей задачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...