2

次のようなリストがあります。

lst = [1,2,6,3,9]

リスト内のすべての数値を合計し、この値を新しいリストに追加する関数を作成し、リストをウォークスルーして値を 1 つずつ削除し、値を合計したいと考えています。関数は次の計算を実行します。

result = [[1+2+6+3+9],
          [1+6+3+9],
          [1+2+3+9],
          [1+2+6+9],
          [1+2+6+3]]

私が説明しようとしている関数は、上記のリストの例を考えると、次の結果を生成します。

[21,19,15,18,12]

Haskell でこの関数を実装する方法を理解するのに苦労しています。具体的には、リストをトラバースし、1 つの要素を削除するが、削除される値を毎回 1 ずつ増やす方法。誰でも助けることができますか?ありがとう。フォールドを使用するヘルパー関数を作成しようとしましたが、「反復」ごとに最後の要素とは異なる要素をドロップする方法がわかりません。

4

2 に答える 2

12

これらの行に沿って何かを書くことができます:

f xss@(x:xs) = total : map (total -) xs
  where total = sum xss

基本的には、最初にリストの合計を取得し、次に各要素について、この同じ合計からこの要素を差し引いたものを取得することを示しています (そして、頭をスキップします)。

詳細については:

  • (x:xs)指定されたリストのパターン マッチに使用されるため、使用するだけで後で簡単にヘッドをスキップできます。xs
  • xss@...リスト全体を簡単に使用できるように、パターン全体に名前を付けるために使用されます
  • where 句は、リストの合計を保持する変数を導入します。このようにして、何度も再計算されることはありません (とにかく最適化されている可能性があります。このように確信しています)。
  • (total -)は演算子セクションです: 引数xで呼び出されると、返されますtotal - x

注: この関数に空のリストが与えられたときに何が起こるかを正確に説明する必要があります。たとえば、空のリストを返すようにしたい場合は、次を追加します。

f [] = []

編集: についての説明map (total -) xs:

上記のリストで詳しく説明したように(total -)、次の機能を提供する演算子セクションです。

\x -> total - x

合計から指定された値を引いた値を返します。

次に、その関数を に与えられたリストの末尾にマップしますf。たとえばf、リストを指定すると

[1, 2, 6, 3, 9]

それは私がマッピングされます

[2, 6, 3, 9]

total が の場合21、map 呼び出しの結果は

[19, 15, 18, 12] -- [21 - 2, 21 - 6, 21 - 3, 21 - 9]
于 2012-09-02T20:36:13.967 に答える
9

(+)Mogは、連想的で可換であり、逆であるという事実を利用する答えを出しました。ただし、どの操作でも機能する答えを出すことも建設的だと思います。つまり、合計する実際のリストを作成してから、それらを合計します。したがって、計画は次のようになります。

  1. 可能な位置ごとにリストを分割する関数を記述します。
  2. 分割時に要素をドロップすることにより、分割をリストに戻す関数を記述します。
  3. リストを合計する関数を記述します(すでにPreludesum関数を使用して実行されています)。
  4. それらを組み合わせ、リスト全体の特殊なケースを含む関数を記述します。

パート1を行うにはいくつかの方法があります。最初の選択肢は明示的な再帰です。

splits :: [a] -> [([a], [a])]
splits []     = [([],[])]
splits (x:xs) = ([],x:xs) : map (\(b,e) -> (x:b,e)) (splits xs)

ghciでチェックして、正しく設定されていることを確認できます。

*Main> splits "abcde"
[("","abcde"),("a","bcde"),("ab","cde"),("abc","de"),("abcd","e"),("abcde","")]

ただし、もっと良い方法があります。このData.Listモジュールには、特定の方法でリストを変更するための一連の関数が含まれています。tailsそれらの2つはとですinits

*Main> tails "abcde"
["abcde","bcde","cde","de","e",""]
*Main> inits "abcde"
["","a","ab","abc","abcd","abcde"]

したがって、この定義は見栄えがはるかに良くなります。

splits xs = zip (inits xs) (tails xs)

ここで、各位置から1つの要素が削除されたリストのリストを生成する関数が必要です。

dropEach xs = [beginning ++ end | (beginning, ignored:end) <- splits xs]

したがって、最後のステップはすべてをまとめることです。

funnySums xs = map sum (xs : dropEach xs)

テストできます:

*Main> funnySums [1, 10, 100, 1000, 10000]
[11111,11110,11101,11011,10111,1111]
于 2012-09-02T21:19:12.943 に答える