3
+2-1+18*+7-21+3*-4-5+6x29

上記の文字列は、key=>value配列または同様のものに分割しようとしている種類の文字列の例です。この文字列は、イントラネットサイトの3列のページにあるさまざまなクラスのレイアウトを表すために使用されます。このページは、ユーザーがドラッグアンドドロップで編集できます。この文字列はCookieに保存され、次回の訪問時に使用されます。

数字はクラスのIDを表し、は-クラスの状態(最小化、拡張、非表示)を表し、は列の区切りを表します。+x*

explodeを使用して、これを列に簡単に分割できます。これにより、3つ$key => $valueの関連付けが与えられて配列されます。

例えば。

$column_layout = array( [0] => '+2-1+18' , [1] => '+7-21+3' , [2] => '-4-5+6x29' )

次に、これをそこからさまざまなクラスに分割し、ステータスとIDを一緒に保つ必要があります。さまざまなクラスとステータスがユーザーごとに異なり、各列にいくつあるかが変わるため、これをすべて自動的に実行できるようにする必要があります。

$column1 = array(
    array( '+' , 2 ),
    array( '-' , 1 ),
    array( '+' , 18 )
);
$column2 = array(...
4

2 に答える 2

7

まずexplode()、区切り文字を含む配列*

次に、preg_match_allを使用して、展開された配列の各アイテムを照合できます。このようなものは、入力例で機能します。

$layout = explode('*', $input);
$columns = array();
foreach ( $layout as $item ){
    $parts = array();

    //matches either a -, x or + followed by one or more digits
    preg_match_all('/([+-x])(\d+)/', $item, $matches, PREG_SET_ORDER);

    foreach ( $matches as $match){ 
        //match[1] hold the + or -, match[2] holds the digits
        $parts[] = array($match[1], $match[2]);
    }
    $columns[] = $parts;
}

例からの出力は次のようになります。

array(
     array( array('+', '2'), array('-', '1'), array('+', '18') ),
     array( array('+', '7'), array('-', '21'), array('+', '3') ),
     //etc
);

PHP 5.3では、このようなものを使用できます(テストされていません)。主な違いは、内側のループがに置き換えられていることarray_mapです。これにより、多くのコード行が不要になります。(配列マップは、配列内のすべての項目に関数を適用し、変換された配列を返します)。素敵なクロージャ構文にはPHP5.3が必要です

$layout = explode('*', $input);
$columns = array();
foreach ( $layout as $item ){
    preg_match_all('/([+-x])(\d+)/', $item, $matches, PREG_SET_ORDER);
    $columns[] = array_map( function($a){ return array($a[1], $a[2]); },
                            $matches);
}

ループを完全に削除することもできます。

$innerMatch = function($item){
    preg_match_all('/([+-x])(\d+)/', $item, $matches, PREG_SET_ORDER);
    return array_map( function($a){ return array($a[1], $a[2]); },
                      $matches);
};
$columns = array_map($innerMatch, explode('*', $input));

ただし、これには、ほとんどのPHP開発者が読みにくいという大きな欠点があるため、使用をお勧めしません。


詳細説明

@ChristopherAltmanのリクエストで

PHP 5.3バージョンの唯一の新しいビットは、実際には次のとおりです。

array_map(
          function($a){ return array($a[1], $a[2]); },
          $matches
);

少し拡張して変更します(例として)

//bind an anonymous function to the variable $func
$func = function($a){
    return $a*$a; 
}; 
//$func() now calls the anonymous function we have just defined

//then we can call it like so:
$result = array_map($func, $myArray);

したがって、次のよう$myArrayに定義されている場合

array(1,2,3,4);

配列マップ関数を実行すると、次のように変換すると考えることができます。

array(func(1),func(2),func(3),func(4));

ただし、PHPは怠惰な言語ではないため、すべての関数は検出されるとすぐに評価されるため、配列はarray_mapから次のように返されます。

array(2, 4, 9, 16)

実際のコードでpreg_match_allは、一致の配列を返します(一致は配列です)。したがって、私が行うのは配列を取得し、一致するたびに、一致を必要な形式の別の配列に変換する関数を適用することです。

于 2010-04-19T12:35:02.647 に答える
0

厳密にフォーマットされた入力に静的な数のセグメントとセグメントごとの値があると仮定するとsscanf()、テクニックの代わりに文字列を解析する(冗長な)直接的な方法として使用することにはいくつかの利点がありpreg_ます。

  1. これは、直接的な単一機能の手法です。爆発してから解析する必要はありません。
  2. この関数によって生成される無駄な「フルストリング一致」はありpreg_match()ません。
  3. 配列から必要なものを選択する必要はありません$matches(のようにpreg_match()
  4. 数値はすでに整数としてキャストされています(それが役立つ場合)。

コード:(デモ

$layout = '+2-1+18*+7-21+3*-4-5+6x29';

sscanf(
    $layout,
    '%[-+x]%d%[-+x]%d%[-+x]%d*%[-+x]%d%[-+x]%d%[-+x]%d*%[-+x]%d%[-+x]%d%[-+x]%d',
    $column1[0][0], $column1[0][1], $column1[1][0], $column1[1][1], $column1[2][0], $column1[2][1],
    $column2[0][0], $column2[0][1], $column2[1][0], $column2[1][1], $column2[2][0], $column2[2][1],
    $column3[0][0], $column3[0][1], $column3[1][0], $column3[1][1], $column3[2][0], $column3[2][1]
);

var_export($column1);
echo "\n---\n";
var_export($column2);
echo "\n---\n";
var_export($column3);

出力:

array (
  0 => 
  array (
    0 => '+',
    1 => 2,
  ),
  1 => 
  array (
    0 => '-',
    1 => 1,
  ),
  2 => 
  array (
    0 => '+',
    1 => 18,
  ),
)
---
array (
  0 => 
  array (
    0 => '+',
    1 => 7,
  ),
  1 => 
  array (
    0 => '-',
    1 => 21,
  ),
  2 => 
  array (
    0 => '+',
    1 => 3,
  ),
)
---
array (
  0 => 
  array (
    0 => '-',
    1 => 4,
  ),
  1 => 
  array (
    0 => '-',
    1 => 5,
  ),
  2 => 
  array (
    0 => '+',
    1 => 6,
  ),
)

ps

  • 結果を3つの第1レベルの要素と、3組のシンボル番号サブ配列を含む要素を含む単一の配列にしたい場合は、の参照変数を変更することでもこれを実現できますsscanf()
  • フォーマット文字列での繰り返しが気に入らない場合は、繰り返されるサブパターンを変数として宣言し、代わりにプログラムで繰り返すことができます(もちろんアスタリスクで区切られます)。
于 2021-08-10T22:04:35.677 に答える