php 在php中循环多维数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1551822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Looping a multidimensional array in php
提问by errata
I have a multidimensional array like this:
我有一个像这样的多维数组:
array(2) {
[1]=>
array(3) {
["eventID"]=>
string(1) "1"
["eventTitle"]=>
string(7) "EVENT 1"
["artists"]=>
array(3) {
[4]=>
array(2) {
["name"]=>
string(8) "ARTIST 1"
["description"]=>
string(13) "artist 1 desc"
["links"]=>
array(2) {
[1]=>
array(2) {
["URL"]=>
string(22) "http://www.artist1.com"
}
[6]=>
array(2) {
["URL"]=>
string(24) "http://www.artist1-2.com"
}
}
}
[5]=>
array(2) {
["name"]=>
string(8) "ARTIST 8"
["description"]=>
string(13) "artist 8 desc"
["links"]=>
array(1) {
[8]=>
array(2) {
["URL"]=>
string(22) "http://www.artist8.com"
}
}
}
[2]=>
array(2) {
["ime"]=>
string(8) "ARTIST 5"
["opis"]=>
string(13) "artist 5 desc"
["links"]=>
array(1) {
[9]=>
array(2) {
["URL"]=>
string(22) "http://www.artist5.com"
}
}
}
}
}
[2]=>
array(3) {
["eventID"]=>
string(1) "2"
["eventTitle"]=>
string(7) "EVENT 2"
["artists"]=>
array(3) {
[76]=>
array(2) {
["name"]=>
string(9) "ARTIST 76"
["description"]=>
string(14) "artist 76 desc"
["links"]=>
array(1) {
[13]=>
array(2) {
["URL"]=>
string(23) "http://www.artist76.com"
}
}
}
[4]=>
array(2) {
["name"]=>
string(8) "ARTIST 4"
["description"]=>
string(13) "artist 4 desc"
["links"]=>
array(1) {
[11]=>
array(2) {
["URL"]=>
string(22) "http://www.artist4.com"
}
}
}
}
}
}
I would like to make html output like this:
我想像这样制作html输出:
--
——
EVENT 1
ARTIST 1
artist 1 desc
http://www.artist1.com, http://www.artist1-2.com
事件 1
艺术家 1
艺术家 1 描述
http://www.artist1.com, http://www.artist1-2.com
ARTIST 8
artist 8 desc
http://www.artist8.com
艺术家 8
艺术家 8 描述
http://www.artist8.com
ARTIST 5
artist 5 desc
http://www.artist5.com
艺术家 5
艺术家 5 描述
http://www.artist5.com
--
——
EVENT 2
ARTIST 76
artist 76 desc
http://www.artist76.com
活动 2
艺术家 76
艺术家 76 描述
http://www.artist76.com
ARTIST 4
artist 4 desc
http://www.artist4.com
艺术家 4
艺术家 4 描述
http://www.artist4.com
--
——
etc.
等等。
I'm confused about digging deeper and deeper in arrays, especially when my array keys are not sequential numbers but IDs of artist/link/etc.
These arrays will kill me, honestly! =)
我对在数组中越来越深入地挖掘感到困惑,尤其是当我的数组键不是序列号而是艺术家/链接/等的 ID 时。
老实说,这些阵列会杀了我!=)
Thanks for any help in advance!!!
提前感谢您的任何帮助!!!
回答by richsage
You're best using the foreachconstruct to loop over your array. The following is untested and is off the top of my head (and probably therefore not as thought through as it should be!) but should give you a good start:
您最好使用该foreach构造来遍历您的数组。以下内容未经测试且不在我的脑海中(因此可能没有经过深思熟虑!),但应该给您一个良好的开端:
foreach ($mainArray as $event)
{
print $event["eventTitle"];
foreach ($event["artists"] as $artist)
{
print $artist["name"];
print $artist["description"];
$links = array();
foreach ($artist["links"] as $link)
{
$links[] = $link["URL"];
}
print implode(",", $links);
}
}
回答by Jed Smith
The foreachstatement will take care of all of this for you, including the associative hashes. Like this:
该foreach语句将为您处理所有这些,包括关联哈希。像这样:
foreach($array as $value) {
foreach($value as $key => $val) {
if($key == "links") {
}
/* etc */
}
}
回答by Warbo
I think a good way to approach this is "bottom up", ie. work out what to do with the inner-most values, then use those results to work out the next-level-up, and so on until we reach the top. It's also good practice to write our code in small, single-purpose, re-usable functions as much as possible, so that's what I'll be doing.
我认为解决这个问题的一个好方法是“自下而上”,即。找出如何处理最内部的值,然后使用这些结果来计算下一个级别,依此类推,直到我们到达顶部。尽可能用小的、单一用途的、可重用的函数编写我们的代码也是一种很好的做法,这就是我要做的。
Note that I'll assume your data is safe (ie. it's not been provided by a potentially-malicious user). I'll also assume that the keys "ime" and "opi" are meant to match the "name" and "description" of the other arrays ;)
请注意,我会假设您的数据是安全的(即它不是由潜在恶意用户提供的)。我还将假设键“ime”和“opi”旨在匹配其他数组的“名称”和“描述”;)
We can ignore the innermost strings themselves, since we don't need to modify them. In that case the inner-most structure I can see are the individual links, which are arrays containing a 'URL' value. Here's some code to render a single link:
我们可以忽略最里面的字符串本身,因为我们不需要修改它们。在这种情况下,我能看到的最内部结构是各个链接,它们是包含“URL”值的数组。下面是一些渲染单个链接的代码:
function render_link($link) {
return "<a href='{$link['URL']}'>{$link['URL']}</a>";
}
This has reduced an array down to a string, so we can use it remove the inner-most layer. For example:
这将数组缩减为字符串,因此我们可以使用它删除最内层。例如:
// Input
array('URL' => "http://www.artist1.com")
// Output
"<a href='http://www.artist1.com'>http://www.artist1.com</a>"
Now we move out a layer to the 'links' arrays. There are two things to do here: apply "render_link" to each element, which we can do using "array_map", then reduce the resulting array of strings down to a single comma-separated string, which we can do using the "implode" function:
现在我们将一层移出到“链接”数组。这里有两件事要做:将“render_link”应用于每个元素,我们可以使用“array_map”来完成,然后将结果字符串数组缩减为一个逗号分隔的字符串,我们可以使用“implode”来完成功能:
function render_links($links_array) {
$rendered_links = array_map('render_link', $links_array);
return implode(', ', $rendered_links);
}
This has removed another layer, for example:
这已经删除了另一层,例如:
// Input
array(1 => array('URL' => "http://www.artist1.com"),
6 => array('URL' => "http://www.artist1-2.com"))
// Output
"<a href='http://www.artist1.com'>http://www.artist1.com</a>, <a href='http://www.artist1-2.com'>http://www.artist1-2.com</a>"
Now we can go out another level to an individual artist, which is an array containing 'name', 'description' and 'links'. We know how to render 'links', so we can reduce these down to a single string separated by linebreaks:
现在我们可以进入另一个级别到单个艺术家,这是一个包含“名称”、“描述”和“链接”的数组。我们知道如何呈现“链接”,因此我们可以将它们缩减为由换行符分隔的单个字符串:
function render_artist($artist) {
// Replace the artist's links with a rendered version
$artist['links'] = render_links($artist['links']);
// Render this artist's details on separate lines
return implode("\n<br />\n", $artist);
}
This has removed another layer, for example:
这已经删除了另一层,例如:
// Input
array('name' => 'ARTIST 1',
'description' => 'artist 1 desc',
'links' => array(
1 => array(
'URL' => 'http://www.artist1.com')
6 => array(
'URL' => 'http://www.artist1-2.com')))
// Output
"ARTIST 1
<br />
artist 1 desc
<br />
<a href='http://www.artist1.com'>http://www.artist1.com</a>, <a href='http://www.artist1-2.com'>http://www.artist1-2.com</a>"
Now we can move out a layer to the 'artists' arrays. Just like when we went from a single link to the 'links' arrays, we can use array_map to handle the contents and implode to join them together:
现在我们可以将图层移出到“艺术家”数组。就像我们从单个链接到“链接”数组一样,我们可以使用 array_map 来处理内容并内爆将它们连接在一起:
function render_artists($artists) {
$rendered = array_map('render_artist', $artists);
return implode("\n<br /><br />\n", $rendered);
}
This has removed another layer (no example, because it's getting too long ;) )
这已经删除了另一层(没有示例,因为它太长了;))
Next we have an event, which we can tackle in the same way we did for the artist, although I'll also remove the ID number and format the title:
接下来我们有一个事件,我们可以像处理艺术家一样处理它,但我也会删除 ID 号并格式化标题:
function render_event($event) {
unset($event['eventID']);
$event['eventTitle'] = "<strong>{$event['eventTitle']}</strong>";
$event['artists'] = render_artists($event['artists']);
return implode("\n<br />\n", $event);
}
Now we've reached the outer array, which is an array of events. We can handle this just like we did for the arrays of artists:
现在我们已经到达了外部数组,它是一个事件数组。我们可以像处理艺术家数组一样处理这个问题:
function render_events($events) {
$rendered = array_map('render_event', $events);
return implode("\n<br /><br />--<br /><br />", $rendered);
}
You might want to stop here, since passing your array to render_events will give you back the HTML you want:
您可能想停在这里,因为将您的数组传递给 render_events 将返回您想要的 HTML:
echo render_events($my_data);
However, if we want more of a challenge we can try to refactor the code we've just written to be less redundant and more re-usable. One simple step is to get rid of render_links, render_artists and render_events since they're all variations on a more-general pattern:
然而,如果我们想要更多的挑战,我们可以尝试重构我们刚刚编写的代码,以减少冗余并提高可重用性。一个简单的步骤是摆脱 render_links、render_artists 和 render_events,因为它们都是更通用模式的变体:
function reduce_with($renderer, $separator, $array) {
return implode($separator, array_map($renderer, $array));
}
function render_artist($artist) {
$artist['links'] = reduce_with('render_link', ', ', $artist['links']);
return implode("\n<br />\n", $artist);
}
function render_event($event) {
unset($event['eventID']);
$event['eventTitle'] = "<strong>{$event['eventTitle']}</strong>";
$event['artists'] = reduce_with('render_artist',
"\n<br /><br />\n",
$event['artists']);
return implode("\n<br />\n", $event);
}
echo reduce_with('render_event', "\n<br /><br />--<br /><br />", $my_data);
If this is part of a larger application, we may want to tease out some more general patterns. This makes the code slightly more complex, but much more re-usable. Here are a few patterns I've spotted:
如果这是更大应用程序的一部分,我们可能需要梳理出一些更通用的模式。这使得代码稍微复杂一些,但更易于重用。以下是我发现的一些模式:
// Re-usable library code
// Partial application: apply some arguments now, the rest later
function papply() {
$args1 = func_get_args();
return function() use ($args1) {
return call_user_func_array(
'call_user_func',
array_merge($args1, func_get_args()));
};
}
// Function composition: chain functions together like a(b(c(...)))
function compose() {
$funcs = array_reverse(func_get_args());
$first = array_shift($funcs);
return function() use ($funcs, $first) {
return array_reduce($funcs,
function($x, $f) { return $f($x); },
call_user_func_array($first, func_get_args()));
};
}
// Transform or remove a particular element in an array
function change_elem($key, $func, $array) {
if is_null($func) unset($array[$key]);
else $array[$key] = $func($array[$key]);
return $array;
}
// Transform all elements then implode together
function reduce_with($renderer, $separator) {
return compose(papply('implode', $separator),
papply('array_map', $renderer));
}
// Wrap in HTML
function tag($tag, $text) {
return "<{$tag}>{$text}</{$tag}>";
}
// Problem-specific code
function render_link($link) {
return "<a href='{$link['URL']}'>{$link['URL']}</a>";
}
$render_artist = compose(
papply('implode', "\n<br />\n"),
papply('change_elem', 'links', papply('reduce_with',
'render_link',
', '));
$render_event = compose(
papply('implode', "\n<br />\n"),
papply('change_elem', null, 'eventID'),
papply('change_elem', 'eventTitle', papply('tag', 'strong')),
papply('change_elem', 'artists', papply('reduce_with',
$render_artist,
"\n<br /><br />\n")));
echo reduce_with($render_event, "\n<br /><br />--<br /><br />", $my_data);

