14

リストのn番目の要素が表示されることは知っxs !! nていますが、そのリストのn番目の要素を編集する方法がわかりません。リストのn番目の要素を編集する方法、または少なくともヒントを与える方法を教えてください。

たとえば、これで2番目の要素'a'をanにするにはどうすればよいですか?'e'['s','t','a','c','k']

4

5 に答える 5

21

n番目の要素を変更する

多くの言語での一般的な操作は、配列内のインデックス付きの位置に割り当てることです。Pythonでは、次のことができます。

>>> a = [1,2,3,4,5]
>>> a[3] = 9
>>> a
[1, 2, 3, 9, 5]

レンズパッケージは、オペレーターにこの機能を提供します (.~)。Pythonとは異なり、元のリストは変更されませんが、新しいリストが返されます。

> let a = [1,2,3,4,5]
> a & element 3 .~ 9
[1,2,3,9,5]
> a
[1,2,3,4,5]

element 3 .~ 9は単なる関数であり、レンズ(&)パッケージの一部であるオペレーターは、 単なる逆関数アプリケーションです。これは、より一般的な関数適用です。

> (element 3 .~ 9) [1,2,3,4,5]
[1,2,3,9,5]

割り当ては、sの任意のネストで完全に正常に機能しTraversableます。

> [[1,2,3],[4,5,6]] & element 0 . element 1 .~ 9
[[1,9,3],[4,5,6]]

また

> set (element 3) 9 [1,2,3,4,5,6,7]

または、複数の要素を有効にする場合は、次を使用できます。

> over (elements (>3)) (const 99) [1,2,3,4,5,6,7]
> [1,2,3,4,99,99,99]

リスト以外のタイプの操作

これはリストだけに限定されるものではありませんが、Traversable型クラスのインスタンスであるすべてのデータ型で機能します。

たとえば、同じ手法が標準の コンテナパッケージからのツリーで機能するとします。

 > import Data.Tree
 > :{
 let
  tree = Node 1 [
       Node 2 [Node 4[], Node 5 []]
     , Node 3 [Node 6 [], Node 7 []]
     ]
 :}
> putStrLn . drawTree . fmap show $ tree
1
|
+- 2
|  |
|  +- 4
|  |
|  `- 5
|
`- 3
   |
   +- 6
   |
   `- 7
> putStrLn . drawTree . fmap show $ tree & element 1 .~ 99
1
|
+- 99
|  |
|  +- 4
|  |
|  `- 5
|
`- 3
   |
   +- 6
   |
   `- 7
> putStrLn . drawTree . fmap show $ tree & element 3 .~ 99
1
|
+- 2
|  |
|  +- 4
|  |
|  `- 99
|
`- 3
   |
   +- 6
   |
   `- 7
> putStrLn . drawTree . fmap show $ over (elements (>3)) (const 99) tree
1
|
+- 2
|  |
|  +- 4
|  |
|  `- 5
|
`- 99
   |
   +- 99
   |
   `- 99
于 2013-03-20T18:30:11.190 に答える
17

Haskellは関数型言語であるため、すべてが不変であるため、リスト内の要素を「編集」することはできません。代わりに、次のような新しいリストを作成できます。

take n xs ++ [newElement] ++ drop (n + 1) xs

ただし、Haskellでは推奨されていません。詳細については、この投稿を参照してください:リスト内のHaskell置換要素

于 2013-03-20T17:36:14.167 に答える
10

リストのn番目の要素を編集することはできません。値は不変です。新しいリストを作成する必要があります。ただし、不変性のため、変更された要素の後の部分を元のリストと共有できます。

したがって、リストのn番目の要素に変換を適用する場合(および前後の部分が同一である場合)、3つの部分があります。

  • 問題の要素の前のリストの先頭、たとえばfront
  • 問題の要素、言うelement
  • 問題の要素の後のリストの後ろ、たとえばback

次に、パーツを組み立てます

front ++ transform element : back

ですから、興味深い部分をうまく把握することは残っています。

splitAt :: Int -> [a] -> ([a],[a])

これにより、リストの最初の部分が返されsplitAt idx list、インデックスの前がidxペアの最初のコンポーネントとして返され、残りが2番目のコンポーネントとして返されます。

changeNthElement :: Int -> (a -> a) -> [a] -> [a]
changeNthElement idx transform list
    | idx < 0   = list
    | otherwise = case spliAt idx list of
                    (front, element:back) -> front ++ transform element : back
                    _ -> list    -- if the list doesn't have an element at index idx

(注:私は0から要素のカウントを開始しました。1からカウントを開始する場合は、調整して使用する必要がありますidx-1。)

于 2013-03-20T17:34:19.530 に答える
2

次の方法がまだ言及されていないことに驚いたので、さらに参照できるように追加します。

replace index elem = map (\(index', elem') -> if index' == index then elem else elem') . zip [0..]

> replace 2 'e' "stack"
"steck"

範囲外のインデックスのキャスを処理します。

> replace (-1) 'z' "abc"
"abc"
> replace 0 'z' "abc"
"zbc"
> replace 2 'z' "abc"
"abz"
> replace 3 'z' "abc"
"abc"

splitAtメソッド(O(2N))より遅くはありません。

于 2020-02-24T16:49:45.937 に答える
0

単純な再帰的ソリューションを作成する可能性もあります。

基本的な考え方は、リストの要素#5を置き換えるには、そのリストの末尾の要素#4を置き換えるだけでよいということです。

@DanielFisherの回答からの表記を使用すると、次のコードが得られます。

changeNthElement :: Int -> (a -> a) -> [a] -> [a]
changeNthElement n fn   []    =  []   -- nothing to change
changeNthElement n fn (x:xs)
    |  (n < 0)    =  x:xs             -- no change for a negative index
    |  (n == 0)   =  (fn x) : xs                          -- easy case
    |  otherwise  =  x : (changeNthElement (n-1) fn xs)   -- recursion

新しい値が古い値に依存しない場合は、上記の関数を特殊化できます。

setNthElement :: Int -> a  -> [a] -> [a]
setNthElement n v xs = changeNthElement n (const v) xs

テスト:

$ ghci
 GHCi, version 8.8.4: https://www.haskell.org/ghc/  :? for help
 ...
 λ> 
 λ> :load q15530511.hs
 [1 of 1] Compiling Main             ( q15530511.hs, interpreted )
 Ok, one module loaded.
 λ> 
 λ> xs = replicate 10 7
 λ> 
 λ> xs
 [7,7,7,7,7,7,7,7,7,7]
 λ> 
 λ> changeNthElement  3 (+2) xs
 [7,7,7,9,7,7,7,7,7,7]
 λ> 
 λ> setNthElement 2 42 xs
 [7,7,42,7,7,7,7,7,7,7]
 λ> 

于 2022-01-25T18:39:25.857 に答える