1

葉への各フルパスが個別の戻り値になるように、複数の葉ノードを持つ配列を平坦化する最良の方法は何ですか?

array("Object"=>array("Properties"=>array(1, 2)));

得た

  1. オブジェクト.プロパティ.1
  2. オブジェクト.プロパティ.2

Object.Properties.1 にフラット化できますが、2 は再帰関数で処理されません。

function flattenArray($prefix, $array)
{
    $result = array();
    foreach ($array as $key => $value)
    {
        if (is_array($value))
            $result = array_merge($result, flattenArray($prefix . $key . '.', $value));
        else
            $result[$prefix . $key] = $value;
    }   
    return $result;
}

複数のリーフノードが予想される場合、トップダウンは機能しないと思われるため、何らかのタイプのボトムアップ処理またはリーフとプロセスごとに配列をコピーする方法が必要です (ただし、これは完全に非効率的と思われます)。

4

3 に答える 3

2
function flatten(array $data, $separator = '.') {
  $result = array();
  $stack = array();
  $path = null;

  reset($data);
  while (!empty($data)) {
    $key = key($data);
    $element = $data[$key];
    unset($data[$key]);  
    if (is_array($element)) {
      if (!empty($data)) {
        $stack[] = array($data, $path);
      }
      $data = $element;
      $path .= $key . $separator;
    } else {
      $result[$path . $key] = $element;
    }

    if (empty($data) && !empty($stack)) {
      list($data, $path) = array_pop($stack);
    }
  }
  return $result;
}

var_dump(flatten(array("Object"=>array("Properties"=>array(1, 2)))));

出力:

array(2) {
  ["Object.Properties.0"]=>
  int(1)
  ["Object.Properties.1"]=>
  int(2)
}
于 2012-09-06T22:00:48.193 に答える
1

Kdyby Frameworkの関数 flatMapAssoc() を使用します。

$flattened= array();
flatMapAssoc($array, function ($value, $keys) use (&$flattened) {
        $flattened[implode('.', $keys)] = $value;
});



/**
 * @param array|\Traversable $array
 * @param callable $callback
 * @return array
 */
    function flatMapAssoc($array, $callback)
{
    $callback = callback($callback);
    $result = array();
    $walker = function ($array, $keys = array()) use (&$walker, &$result, $callback) {
        foreach ($array as $key => $value) {
            $currentKeys = $keys + array(count($keys) => $key);
            if (is_array($value)) {
                $walker($value, $currentKeys);
                continue;
            }
            $result[] = $callback($value, $currentKeys);
        }

        return $result;
    };

    return $walker($array);
}
于 2012-09-06T21:34:07.827 に答える
1

ラッパー関数を使用して実装の詳細 (プレフィックス パラメーター) を非表示にし、if 分岐を追加して空の配列をテストします。最後に、単純なリーフの場合、$value変数ではなく変数を使用する必要があります$key

$x = array("Object"=>array("Properties"=>array(1, 2), "test"=>array(), "post"));

function flatten ($array) {
    return flattenArray('',$array);
}

function flattenArray($prefix, $array) {
    $result = array();
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            if(count($value)) {
                $result = array_merge($result, flattenArray($prefix."$key.", $value));
            } else {
                $result[] = "$prefix$key";
            }
        } else {
            $result[] = "$prefix$value";
        }
    }   
    return $result;
}

echo join("\n", flatten($x));

ツリー構造を模倣したい場合は、別の配列構造を使用できます。このようなもの:

$y = array ("Object", 
            array("Properties", 1, 2),
            "test",
            "post"
);

flattenArray は次のようになります。

function flattenArray($prefix, $array) {
    $result = array();
    $prefix .=array_shift($array).'.';
    foreach ($array as $value) {
        if (is_array($value)) {
            $result = array_merge($result, flattenArray($prefix, $value));
        } else {
            $result[] = "$prefix$value";
        }
    }   
    return $result;
}
于 2012-09-06T22:37:52.570 に答える