3

このチュートリアルに従って、DOMを使用してhtmlを解析するための高度な(私にとって)perl構文を理解しようとしています:

say "div days:";
say $_->text for $dom->find('div.days')->each;

say "\nspan hours:";
say $_->text for $dom->find('span.hours')->each;

この構文はどういう意味ですか? これは何のループですか?Classic for construction は次のようになりますfor(i=0;i<10;i++){ code }{code} for (some_condition)

また、このコンテキストで「各」キーワードは何を意味しますか? eachPerl 組み込み関数と共通するものがありますか、それとも Mojo::DOM に固有のものですか? eachMojo::Dom の下にある場合は、Mojo::DOM ホームページで言及する必要があると思います。しかし、彼らのサイトのメソッドセクションのeach下にについての言及が見つからなかったので、これは Perl の組み込み関数であるに違いありません。しかし、この組み込み関数の構文はまったく異なります。どうしてこれが可能なのでしょうか?each

チュートリアルページの別の例

say "Open Times:";
say for $dom->find('div.openTime')
            ->map(sub{$_->children->each})
            ->map(sub{$_->text})
            ->each;

mapメソッドとメソッドの上記と同じ問題sub

  • それらの「Perlish」コードの断片を、より「C スタイル」の方法で書き直して、理解できるようにすることはできますか?
  • 最も重要なこと: Mojo::DOM に含まれるすべてのメソッドのパラメーターと戻り値をリストする方法は? Perlの場合でもインテリセンス(オートコンプリート)を備えたIDEがあり、このIDEはメソッドの戻り値の型などを認識している必要があると読んだため、何らかの方法で行う必要があります。
4

3 に答える 3

9
say "Open Times:";
say for $dom->find('div.openTime')
            ->map(sub{$_->children->each})
            ->map(sub{$_->text})
            ->each;

これらのキーワード ( findmapeach) はすべて、実際にはキーワードではなく、Mojo::DOM のメソッドです。->それらはオペレーターによって認識できます。

この場合、いくつかのメソッドが連鎖しています。これは、それぞれがそのオブジェクト (この例では$dom) を再び返す場合にのみ可能です。この種の連鎖は JavaScript でよく使用され、特にjQueryなどの最新のフレームワークで使用されます。コードが読みやすくなり、操作が節約されます。

基本的に、チェーン内の複数のトランザクションを適用します。

  1. findすべての要素「div.openTime」
  2. map( それぞれの処理を行います ) 指定されたサブ (これは実際の Perl ですsub):
    1. 現在のすべてchildrenの要素をコレクションとして取得します
    2. それらのリストeach(配列を返すなど)
  3. map特定のサブを持つそれら:
    1. text要素からコンテンツを抽出する
  4. eachそしてそれらのリスト

これはすべて接尾辞でラップされていますforeach(@Quentinが言ったように)。sayでロードできる機能ですuse features qw(say)printと改行文字を組み合わせます。

たぶん、ここで何が起こっているのかがより明確になりました。

my $collection1 = $dom->find('div.oopenTime');

my $collection2 = $collection1->map(
  sub {
    my $collection = $_->children;
    return $collection->each;
  }
);

my collection3 = $collection2->map(
  sub {
    return $_->text;
  }
);

foreach my $text ($collection3) {
  say $text;
}

オートコンプリートを提供する IDE は通常、問題のコードをスキャンして、オブジェクトが持つメソッドを認識します。Perl で特定のオブジェクトまたはパッケージで使用可能なメソッドを一覧表示するにはどうすればよいですか? をご覧ください。またはモジュールのコードを読んでください。さらに良いことに、ドキュメントを読んでください

于 2012-10-10T12:54:49.283 に答える
5

What does this syntax mean, what is going on here ?

It is a postfix for loop.

for (@foo) {
    say $_
}

can be written as

say $_ for @foo;

Also what does "each" keyword mean in this context

It is a method on the object. It returns a list of things in the Mojo::Collection.

于 2012-10-10T12:21:05.507 に答える
3

他の答えは、私がチュートリアルの投稿に書いたことを説明しているようです。つまり、Mojo :: DOM(実際にはMojo :: Collectionクラス)の別の便利なメソッドである、を理解するようになったということを付け加えたいと思いますpluck。この方法は、視覚的な複雑さを軽減します

->map(sub{$_->text})

->pluck('text')

さらに、少なくともいくつかのeach呼び出しが無関係であり、リストコンテキストで使用されるMojo::Collectionが「DoWhatIMean」でeach自動的に実行されることに気付きました。 編集:私はこれをチェックしました、そして実際に文字列として使われるとき、要素は改行で結合されます。これは私が望んでいることではないので、私はeach電話を返しました。

ここで述べているのは、同じチュートリアルスクリプトを今すぐ作成する方法です。

#!/usr/bin/env perl

use strict;
use warnings;

use 5.10.0;
use Mojo::DOM;

my $dom = Mojo::DOM->new(<<'HTML');
<div class="box notranslate" id="venueHours">
<h5 class="translate">Hours</h5>
<div class="status closed">Currently closed</div>
<div class="hours">
  <div class="timespan">
    <div class="openTime">
      <div class="days">Mon,Tue,Wed,Thu,Sat</div>
      <span class="hours"> 10:00 AM–6:00 PM</span>
    </div>
  </div>
  <div class="timespan">
    <div class="openTime">
      <div class="days">Fri</div>
      <span class="hours"> 10:00 AM–9:00 PM</span></div>
    </div>
    <div class="timespan">
      <div class="openTime">
        <div class="days">Sun</div>
        <span class="hours"> 10:00 AM–5:00 PM</span>
      </div>
    </div>
  </div>
</div>
HTML

say "div days:";
say for $dom->find('div.days')->pluck('text')->each;

say "\nspan hours:";
say for $dom->find('span.hours')->pluck('text')->each;

say "\nOpen Times:";
say for $dom->find('div.openTime')
            ->map(sub{$_->children->each})
            ->pluck('text')
            ->each;

メソッドがMojo::Collectionオブジェクトを返す->pluck('children')ため、使用しないことに注意してください。つまり、からの戻り値はコレクションのコレクションになります。構造をフラット化するために、呼び出しの結果を呼び出す必要があるため、その特定の呼び出しを削除することはできません。childrenpluckeachchildren->map

しかし、今、私はこの面倒を一緒に避けられなかったのだろうか?Mojo :: DOMはCSS3セレクターw3schoolsリファレンス)を優れた方法でサポートしています。親(div.openTime)を直接選択するのではなく、セレクターでその子を選択することをお勧めします。

say "\nOpen Times:";
say for $dom->find('div.openTime > *')->pluck('text')->each;

したがって、ここには良い教訓があります。セレクターが必要なコレクションに近いものを提供できるようにすることで、後で変換する必要がなくなります。


最後の質問に答えるには:

これを翻訳するには

say for $dom->find('div.openTime')
            ->map(sub{$_->children->each})
            ->map(sub{$_->text})
            ->each;

もっとC風のPerlに(私はそれをfor(i=0;i<10;i++){ ... }極端にとらえませんが)それは次のように見えるかもしれません

my @open_times = $dom->find('div.openTime')->each;

my @all_children;
foreach my $elem ( @open_times ) {
  my @children = $elem->children->each;
  push @all_children, @children;
}

my @texts;
foreach my $child ( @all_children ) {
  push @texts, $child->text;
}

foreach my $text ( @texts ) {
  print $text . "\n";
}

私がMojo(オブジェクトチェーン)の方法を好む理由がわかると思います。

2番目の質問について:Mojoliciousには、優れた(場合によっては過剰な)ドキュメントがあります。システム全体について学ぶためにここから始めてください。特にMojo::DOMMojo::Collectionについて読むと、 DOMの解析を処理するのに十分なはずです。問題の一部は、DOMオブジェクトとCollectionオブジェクトの相互依存性に気づかなかったため、すべてのメソッド呼び出しがDOMオブジェクトに対して行われたと誤って想定したことだと思います。注意深く読むと、いくつかのDOMメソッド(返されるものは複数の結果を返す可能性があります)がCollectionオブジェクトを返すことがわかります。これfindは、そのようなメソッドの1つです。

于 2012-10-10T15:27:39.830 に答える