在PHP中将1D数组转换为多维数组

时间:2022-10-22 22:57:34

I have this array:

我有这个数组:

Array
(
    [1] => animal
    [1-1] => turtle
    [1-1-1] => sea turtle
    [1-1-2] => box turtle
    [1-1-3] => green turtle
    [1-1-3-1] => green turtle with brown tail
)

and I want some how to convert it into:

我想要一些如何将其转换为:

Array
(
    [1-title] => animal
    [1-sons] => array(
            [1-1-title] => turtle
            [1-1-sons] => array(
                    [1-1-1] => sea turtle
                        [1-1-2] => box turtle
                    [1-1-3-title] => green turtle
                    [1-1-3-sons] => array(
                            [1-1-3-title] => green turtle
                                  )
                    )
              )
)

or maybe you can suggest a better way for organizing the outputted array..

或者你可以建议一个更好的方法来组织输出的数组..

but how to do that?

但是怎么做?

I know that's not easy task at all, I'm writing a parser that will walk on data and make tree out of them..

我知道这根本不是一件容易的事,我正在编写一个解析器来处理数据并从中创建树。

Thanks in advance for your help and advices..

在此先感谢您的帮助和建议..

5 个解决方案

#1


The easiest way of organizing your data would be in such a way:

组织数据的最简单方法是这样:

array (
  'Animal' =>
  array (
    'Turtle' =>
    array (
      'Sea Turtle',
      'Box Turtle',
      'Green Turtle' =>
      array (
        'Green Turtle With Brown Tail',
      ),
      'Common Turtle',
    ),
  ),
);

// Or, otherwise written (equivalent to the above)

$animals = array();
$animals['Animal'] = array();
$animals['Animal']['Turtle'] = array();
$animals['Animal']['Turtle'][] = 'Sea Turtle';
$animals['Animal']['Turtle'][] = 'Box Turtle';
$animals['Animal']['Turtle']['Green Turtle'] = array();
$animals['Animal']['Turtle']['Green Turtle'][] = 'Green Turtle With Brown Tail';
$animals['Animal']['Turtle'][] = 'Common Turtle';

Essentially, the name of the animal is the value, unless it has children, then the value is an array and the key is the animal name.

基本上,动物的名称是值,除非它有子,否则值是一个数组,键是动物名称。


That way, you can easily parse the values by doing the following:

这样,您可以通过执行以下操作轻松解析值:

parse_animals($animals);

function parse_animals($array, $indent = 0) {
  if(!is_array($array)) return;    // A little safe guard in case.

  foreach($array as $key => $value) {
    echo str_repeat('  ', $indent) . "- ";

    if(is_array($value)) {
      echo $key . "\n";
      parse_animals($value, $indent + 1);
    } else {
      echo $value . "\n";
    }
  }
}

The above in the console will output the following:

以上控制台将输出以下内容:

- Animal
  - Turtle
    - Sea Turtle
    - Box Turtle
    - Green Turtle
      - Green Turtle With Brown Tail
    - Common Turtle

EDIT: And here is a version that will output it for a webpage.

编辑:这是一个将其输出为网页的版本。

function parse_animals_web($array) {
  if(!is_array($array)) return;    // A little safe guard in case.

  foreach($array as $key => $value) {
    echo '<ul>';

    if(is_array($value)) {
      echo '<li>' . htmlentities($key) . "</li>";
      parse_animals_web($value);
    } else {
      echo '<li>' . htmlentities($value) . "</li>";
    }

    echo '</ul>';
  }
}

The output is:

输出是:

  • Animal
    • Turtle
    • Sea Turtle
    • Box Turtle
    • Green Turtle
      • Green Turtle With Brown Tail
      • 与棕色尾巴的绿海龟

    • 与棕色尾巴的绿海龟绿海龟

    • Common Turtle
  • 动物龟海龟盒龟绿龟与棕色尾巴共同龟的绿海龟


Maybe you want to get the children of an animal.

也许你想要一个动物的孩子。

function get_children_of($array, $name) {
  foreach($array as $key => $value) {
    if(is_array($value)) {
      if($key === $name) {
        return $value;
      } else {
        return get_children_of($value, $name);
      }
    }
  }

  return array();
}

Now we can get all the children of the Green Turtle and output them.

现在我们可以得到绿海龟的所有孩子并输出它们。

$green_turtle = get_children_of($animals, 'Green Turtle');
parse_array($green_turtle);

The output is:

输出是:

- Green Turtle With Brown Tail

EDIT: Since you say you are stuck with the input array being in that weird format, here is a function that will convert your array into the format I specified above:

编辑:因为你说你被困在输入数组是那种奇怪的格式,这里有一个函数,将您的数组转换为我上面指定的格式:

function convert_array($array) {
  $new_array = array();

  $keys = array_keys($array);
  foreach($keys as $key) {
    $level = explode('-', $key);
    $cur_level = &$new_array;
    $cur_key = '';

    foreach($level as $o_key) {
      $cur_key = ltrim($cur_key . '-' . $o_key, '-');
      $next_key = $cur_key . '-1';
      $value = $array[$cur_key];
      $has_child = array_key_exists($next_key, $array);

      if($has_child) {
        if(!array_key_exists($value, $cur_level)) {
          $cur_level[$value] = array();
        }
        $cur_level = &$cur_level[$value];
      } else {
        $cur_level[] = $value;
      }
    }
  }

  return $new_array;
}

#2


That really depends on how/for what you are going to use the resulting tree. Can you perhaps write down more details about that?

这实际上取决于你将如何使用生成的树。你能写下更多关于这方面的细节吗?

#3


Try this:

$array = array(
    '1' => 'animal',
    '1-1' => 'turtle',
    '1-1-1' => 'sea turtle',
    '1-1-2' => 'box turtle',
    '1-1-3' => 'green turtle',
    '1-1-3-1' => 'green turtle with brown tail'
);
$tree = array();
foreach ($array as $path => $val) {
    $segments = explode('-', $path);
    $last = array_pop($segments);
    $tmp = &$tree;
    $path = '';
    foreach ($segments as $segment) {
        $path .= $segment.'-';
        if (!isset($tmp[$path.'sons'])) {
            $tmp[$path.'sons'] = array();
        }
        $tmp = &$tmp[$path.'sons'];
    }
    $tmp[$path.$last.'-title'] = $val;
}
print_r($tree);

But your data structure doesn’t make much sense.

但是你的数据结构没有多大意义。

#4


What you are trying to achieve is some kind of a nested set and therefore the easiest way to implement it would be to save the parent id in the children's entry:

您要实现的是某种嵌套集,因此实现它的最简单方法是将父ID保存在子项的条目中:

// the tree
0 => array(parent => NULL, name => turtle),
1 => array(parent => 0, name => green turtle),
2 => array(parent => 0, name => blue turtle),
3 => array(parent => 1, name => green turtle with yellow nose)

You can walk through this hierarchy using a simple recursive function.

您可以使用简单的递归函数遍历此层次结构。

If you use objects instead of associative arrays you even get some performance increase.

如果您使用对象而不是关联数组,您甚至会获得一些性能提升。

#5


$result = array();
foreach ($array as $position => $text) {
    $p = explode('-', $position); 
    putIntoTree($result, $p, $text);
}

function putIntoTree( &$tree, $posInfo, $item ) {
    $index = array_shift($posInfo) - 1;

    if (!count($posInfo)) {
        $tree[$index]['name'] = $item;
    } else {         
        if (!isset($tree[$index]['children'])) {
            $tree[$index]['children'] = array();
        }
        putIntoTree($tree[$index]['children'], $posInfo, $item);
    }   
}    

Results in this, which seems a reasonable way to hold the data.

结果,这似乎是一种合理的方式来保存数据。

Array
(
    [0] => Array
        (
            [name] => animal
            [children] => Array
                (
                    [0] => Array
                        (
                            [name] => turtle
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [name] => sea turtle
                                        )

                                    [1] => Array
                                        (
                                            [name] => box turtle
                                        )

                                    [2] => Array
                                        (
                                            [name] => green turtle
                                            [children] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [name] => green turtle with brown tail
                                                        )
                                                )
                                        )
                                )
                        )
                )
        )
)

#1


The easiest way of organizing your data would be in such a way:

组织数据的最简单方法是这样:

array (
  'Animal' =>
  array (
    'Turtle' =>
    array (
      'Sea Turtle',
      'Box Turtle',
      'Green Turtle' =>
      array (
        'Green Turtle With Brown Tail',
      ),
      'Common Turtle',
    ),
  ),
);

// Or, otherwise written (equivalent to the above)

$animals = array();
$animals['Animal'] = array();
$animals['Animal']['Turtle'] = array();
$animals['Animal']['Turtle'][] = 'Sea Turtle';
$animals['Animal']['Turtle'][] = 'Box Turtle';
$animals['Animal']['Turtle']['Green Turtle'] = array();
$animals['Animal']['Turtle']['Green Turtle'][] = 'Green Turtle With Brown Tail';
$animals['Animal']['Turtle'][] = 'Common Turtle';

Essentially, the name of the animal is the value, unless it has children, then the value is an array and the key is the animal name.

基本上,动物的名称是值,除非它有子,否则值是一个数组,键是动物名称。


That way, you can easily parse the values by doing the following:

这样,您可以通过执行以下操作轻松解析值:

parse_animals($animals);

function parse_animals($array, $indent = 0) {
  if(!is_array($array)) return;    // A little safe guard in case.

  foreach($array as $key => $value) {
    echo str_repeat('  ', $indent) . "- ";

    if(is_array($value)) {
      echo $key . "\n";
      parse_animals($value, $indent + 1);
    } else {
      echo $value . "\n";
    }
  }
}

The above in the console will output the following:

以上控制台将输出以下内容:

- Animal
  - Turtle
    - Sea Turtle
    - Box Turtle
    - Green Turtle
      - Green Turtle With Brown Tail
    - Common Turtle

EDIT: And here is a version that will output it for a webpage.

编辑:这是一个将其输出为网页的版本。

function parse_animals_web($array) {
  if(!is_array($array)) return;    // A little safe guard in case.

  foreach($array as $key => $value) {
    echo '<ul>';

    if(is_array($value)) {
      echo '<li>' . htmlentities($key) . "</li>";
      parse_animals_web($value);
    } else {
      echo '<li>' . htmlentities($value) . "</li>";
    }

    echo '</ul>';
  }
}

The output is:

输出是:

  • Animal
    • Turtle
    • Sea Turtle
    • Box Turtle
    • Green Turtle
      • Green Turtle With Brown Tail
      • 与棕色尾巴的绿海龟

    • 与棕色尾巴的绿海龟绿海龟

    • Common Turtle
  • 动物龟海龟盒龟绿龟与棕色尾巴共同龟的绿海龟


Maybe you want to get the children of an animal.

也许你想要一个动物的孩子。

function get_children_of($array, $name) {
  foreach($array as $key => $value) {
    if(is_array($value)) {
      if($key === $name) {
        return $value;
      } else {
        return get_children_of($value, $name);
      }
    }
  }

  return array();
}

Now we can get all the children of the Green Turtle and output them.

现在我们可以得到绿海龟的所有孩子并输出它们。

$green_turtle = get_children_of($animals, 'Green Turtle');
parse_array($green_turtle);

The output is:

输出是:

- Green Turtle With Brown Tail

EDIT: Since you say you are stuck with the input array being in that weird format, here is a function that will convert your array into the format I specified above:

编辑:因为你说你被困在输入数组是那种奇怪的格式,这里有一个函数,将您的数组转换为我上面指定的格式:

function convert_array($array) {
  $new_array = array();

  $keys = array_keys($array);
  foreach($keys as $key) {
    $level = explode('-', $key);
    $cur_level = &$new_array;
    $cur_key = '';

    foreach($level as $o_key) {
      $cur_key = ltrim($cur_key . '-' . $o_key, '-');
      $next_key = $cur_key . '-1';
      $value = $array[$cur_key];
      $has_child = array_key_exists($next_key, $array);

      if($has_child) {
        if(!array_key_exists($value, $cur_level)) {
          $cur_level[$value] = array();
        }
        $cur_level = &$cur_level[$value];
      } else {
        $cur_level[] = $value;
      }
    }
  }

  return $new_array;
}

#2


That really depends on how/for what you are going to use the resulting tree. Can you perhaps write down more details about that?

这实际上取决于你将如何使用生成的树。你能写下更多关于这方面的细节吗?

#3


Try this:

$array = array(
    '1' => 'animal',
    '1-1' => 'turtle',
    '1-1-1' => 'sea turtle',
    '1-1-2' => 'box turtle',
    '1-1-3' => 'green turtle',
    '1-1-3-1' => 'green turtle with brown tail'
);
$tree = array();
foreach ($array as $path => $val) {
    $segments = explode('-', $path);
    $last = array_pop($segments);
    $tmp = &$tree;
    $path = '';
    foreach ($segments as $segment) {
        $path .= $segment.'-';
        if (!isset($tmp[$path.'sons'])) {
            $tmp[$path.'sons'] = array();
        }
        $tmp = &$tmp[$path.'sons'];
    }
    $tmp[$path.$last.'-title'] = $val;
}
print_r($tree);

But your data structure doesn’t make much sense.

但是你的数据结构没有多大意义。

#4


What you are trying to achieve is some kind of a nested set and therefore the easiest way to implement it would be to save the parent id in the children's entry:

您要实现的是某种嵌套集,因此实现它的最简单方法是将父ID保存在子项的条目中:

// the tree
0 => array(parent => NULL, name => turtle),
1 => array(parent => 0, name => green turtle),
2 => array(parent => 0, name => blue turtle),
3 => array(parent => 1, name => green turtle with yellow nose)

You can walk through this hierarchy using a simple recursive function.

您可以使用简单的递归函数遍历此层次结构。

If you use objects instead of associative arrays you even get some performance increase.

如果您使用对象而不是关联数组,您甚至会获得一些性能提升。

#5


$result = array();
foreach ($array as $position => $text) {
    $p = explode('-', $position); 
    putIntoTree($result, $p, $text);
}

function putIntoTree( &$tree, $posInfo, $item ) {
    $index = array_shift($posInfo) - 1;

    if (!count($posInfo)) {
        $tree[$index]['name'] = $item;
    } else {         
        if (!isset($tree[$index]['children'])) {
            $tree[$index]['children'] = array();
        }
        putIntoTree($tree[$index]['children'], $posInfo, $item);
    }   
}    

Results in this, which seems a reasonable way to hold the data.

结果,这似乎是一种合理的方式来保存数据。

Array
(
    [0] => Array
        (
            [name] => animal
            [children] => Array
                (
                    [0] => Array
                        (
                            [name] => turtle
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [name] => sea turtle
                                        )

                                    [1] => Array
                                        (
                                            [name] => box turtle
                                        )

                                    [2] => Array
                                        (
                                            [name] => green turtle
                                            [children] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [name] => green turtle with brown tail
                                                        )
                                                )
                                        )
                                )
                        )
                )
        )
)