5

「/node/143」の形式のクエリ request-uri があります (形式の例にすぎません)。

文字列から最初のスラッシュを取り除きたいので、関数removeを調べて試してみました。私はそれを機能させることができないようです (私は Linux で SBCL を使用しています)。

このコードを使用して request-uri を設定しました。

(setq request-uri "/node/143")

変数をチェックすると、これが返されます。

request-uri
"/node/143"

ここで、最初のスラッシュを削除しようとします (この時点では、関数がどのように適切に使用されているかを確認するだけです)。

(remove "/" request-uri)
"/node/143"

(remove '/ request-uri)
"/node/143"

私もリストを提供しようとしました

(remove '("/") request-uri)
"/node/143"

(remove '('/) request-uri)
"/node/143"

文字列は文字のベクトルですが、何らかの方法で文字列全体が 1 つのセルに配置されるのではないかと考え、全体を削除しようとしましたが、まだ運がありません。

(remove "/node/143" request-uri)
"/node/143"

(remove '/node143 request-uri)
"/node/143"

だから私は今途方に暮れています.この一見単純な機能は本当に私を逃れました.私はドキュメントを手紙に従ったと思っていましたが、何も機能していません.

ここで何が起こっているのか、誰かが光を当てることができますか?

ありがとう。

編集:別の質問を提起した私の質問に対する答えを見つけました。

使用した文字列から要素を削除するには

(remove #\/ request-uri)

文字列全体はどうですか

`(remove #\node request-uri`)

最初の文字に対してのみ機能し、エラーをスローし、次のすべては何もしません。

(remove "node" request-uri)
(remove 'node request-uri)
(remove ?\node request-uri)
(remove #\node request-uri)
(remove '("node") request-uri)

ここで他にどのように対処すればよいかわかりません。

4

4 に答える 4

7

Common Lisp HyperSpecの読み方を学びましょう。

文字列はSequenceArray (文字の 1 次元ベクトル)、そしてStringです。これは、それらの機能のほとんどが適用可能であることを意味します。

REMOVEを見てみましょう。CLHS は次の署名を与えます。

remove item sequence &key from-end test test-not start end count key
    => result-sequence

文字列は一連の文字です。したがって、 remove の呼び出しは次のようになります。

(remove #\/ "/foo/")

または(たとえば)

(remove #\/ "/foo/" :start 2)

注意:#\aは文字です。 #\nodeは文字ではありません。違法。文字列は"/foo/".

文字列から削除する項目は、文字でなければなりません。他には何もありません。なんで?TEST はデフォルトで EQL であり、EQL は文字列内の文字を item 引数と比較するためです。また、キーはデフォルトで IDENTITY であり、アイテムを変更しません。

引数が文字列の場合はどうなりますか? さて、あなたはもっとやらなければなりません:

 (remove "/" "/abc/" :key #'string :test #'equal)

これは、シーケンスの各文字を見て、文字列にします。"/"文字列は、関数 EQUAL を使用してアイテムと比較されます。これも機能します。コストは、 の各文字から文字列を生成する必要があることです"/abc/"。各文字列は新しいオブジェクトです。

それを行う別の方法は次のとおりです。

 (remove "/" "/abc/" :test (lambda (a b) (eql (aref a 0) b)))

上記は、すべてのテストで の最初の文字を取得し"/"、文字列 の文字と比較します"/abc/"。繰り返しますが、コストは、キャラクターを 5 回取得する必要があることです (この例では)。

元のオブジェクトが文字列として来る場合、それを書く最良の方法は次のとおりです。

(remove (aref "/" 0) "/abc/")

上記では、文字列から文字を"/"1 回取得し、REMOVE はこの文字をデフォルトの EQL テストと文字列内の各文字と比較します。これにより、EQL ではない文字の新しい文字列が返されます#\/

?\foo は何だと思いますか? Common Lisp では、これはシンボル|?fOO|です。

(remove "foo" "afoob")文字列 ("foo"ここ) は文字列の要素ではないため、これも機能しません。文字は文字列の要素であることを忘れないでください。また、1 つの項目 like を含む文字列は文字列であり、文字ではないことも忘れないでください"/"。したがって"/"、 と#\/は異なるタイプです。1 つ目は文字列で、2 つ目は文字です。

SUBSEQ は、シーケンスからシーケンスを抽出します。つまり、別の文字列からも文字列を抽出します。

(subseq "0123456" 1 5)
     where 1 is the start and 5 is the end index.

CONCATENATE はシーケンスを追加します。これは、文字列も追加することを意味します。

(concatenate 'string "abc" "123")
  returns a new string with the strings "abc" and "123" appended.

文字列の一部を削除するには、関数 STRING-TRIM、STRING-LEFT-TRIM、および STRING-RIGHT-TRIM も参照してください。

したがって、文字列から部分文字列を削除する別の回答のように、いくつかの文字列を抽出して連結するコードを記述する必要があります。

SEARCH は文字列内の文字列を検索します。

于 2009-03-21T17:36:25.733 に答える
2

部分文字列全体を削除するには、次のような新しい関数を作成する必要があります。

(defun remove-string (rem-string full-string &key from-end (test #'eql)
                      test-not (start1 0) end1 (start2 0) end2 キー)
  "rem-string が削除された完全な文字列を返します"
  (let ((subst-point (rem-string 全文字列を検索)
                             :from-end から-end
                             :test test :test-not test-not
                             :start1 start1 :end1 end1
                             :start2 start2 :end2 end2 :key キー)))
    (サブポイントの場合
        ('文字列を連結
                     (subseq full-string 0 subst-point)
                     (subseq full-string (+ subst-point (length rem-string))))
        フルストリング)))

これは単なる出発点です。SEARCH のすべてのオプションを複製しましたが、一部のオプションはこのコンテキストでは意味をなさないと思います。少なくともこれは機能します:

(remove-string "node" "これはノードかどうか")

より複雑なケースについては、正規表現ライブラリである cl-ppcre を参照してください。

于 2009-03-21T16:47:32.060 に答える
2

説明:

(remove "node" request-uri)
(remove 'node request-uri)
(remove ?\node request-uri)
(remove #\node request-uri)
(remove '("node") request-uri)

これらは (それぞれ) 文字列、(引用符で囲まれた) シンボル、(評価された) シンボル、不正な形式の文字リテラル、1 つの文字列を含むリストです。 REMOVEは、オブジェクトのシーケンスからオブジェクトを削除します。文字列は、これらのシーケンスではありません。

文字列の一部だけを削除したい場合は、SUBSEQ がうまくいくかもしれません:

(let ((uri "/node/143"))
  (when (string= (subseq uri 0 6) "/node/")
    (format t "user wants node ~D" (parse-integer (subseq uri 6)))))

より複雑なものについては、おそらく cl-ppcre や split-sequence のようなライブラリが必要です。(Hunchentoot を使用している場合は、前者が既に読み込まれています。)

于 2009-03-21T17:28:30.323 に答える
0

「/」は文字ではなく文字列であるため、これは失敗します。

(remove "/" request-uri)
"/node/143"

文字が必要な場合は、#/、つまりスラッシュ文字を使用する必要があります。

(remove #\/ request-uri)
"node143"

しかし、ご覧のとおり、すべてのスラッシュが削除されます。リンクしたドキュメント ページによると、remove は :count という名前のキーワード パラメータを受け取ります。これは、削除するアイテムの数を示します。だからあなたはこれを行うことができます。

(remove #\/ request-uri :count 1)
"node/143"

お役に立てれば。

::編集::

?/ ではなく、#/ です。ありがとうダグラス!

于 2009-03-21T15:05:11.323 に答える