在PHP中循环一个多维数组

5

我有一个类似于这样的多维数组:

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"
          }
        }
      }
    }
  }
}

我希望制作出这样的HTML输出:
-- 事件 1
艺术家 1
艺术家1描述
http://www.artist1.com, http://www.artist1-2.com 艺术家 8
艺术家8描述
http://www.artist8.com 艺术家 5
艺术家5描述
http://www.artist5.com -- 事件 2
艺术家 76
艺术家76描述
http://www.artist76.com 艺术家 4
艺术家4描述
http://www.artist4.com --
等等。
我对深入挖掘数组感到困惑,特别是当我的数组键不是连续数字而是艺术家/链接等的ID时。
这些数组会让我疯掉,老实说!=)
提前感谢任何帮助!!!
3个回答

15

最好使用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);
  }
}

9
foreach语句会为您处理所有这些内容,包括关联哈希表。就像这样:
foreach($array as $value) {
    foreach($value as $key => $val) {
        if($key == "links") {

        }
        /* etc */
    }
}

6
我认为一�好的方法是“自下而上�,�先处�最内部的值,然�使用这些结��处�下一个级别,�此类�,直到达到顶部。在�能的情况下,尽�能地编写我们的代�,使其�为����一用途����使用的函数,这也是一个好的�践。
请注�,我将�设您的数�是安全的(�它没有由潜在的��用户�供)。我还将�设键“ime�和“opi�应该�其他数组的“�称�和“�述�匹�😉
我们�以忽略最内部的字符串本身,因为我们�需�修改它们。在这�情况下,我能看到的最内层结�是�独的链�,它们是包�'URL'值的数组。以下是渲染�个链�的代�:
function render_link($link) {
  return "<a href='{$link['URL']}'>{$link['URL']}</a>";
}

这将把一个数组缩减为一个字符串,因此我们可以使用它来移除最内层。例如:
// Input
array('URL' => "http://www.artist1.com")

// Output
"<a href='http://www.artist1.com'>http://www.artist1.com</a>"

现在我们转移到“links”数组的一层。这里有两件事要做:对每个元素应用“render_link”,我们可以使用“array_map”来完成,然后将结果字符串数组减少到单个逗号分隔的字符串,我们可以使用“implode”函数来完成:

function render_links($links_array) {
  $rendered_links = array_map('render_link', $links_array);
  return implode(', ', $rendered_links);
}

这个例子已经删去了另一层,例如:
// 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>"

现在我们可以进入到另一个层级,即个人艺术家,其中包含“名称”、“描述”和“链接”的数组。我们知道如何渲染“链接”,因此我们可以将它们简化为由换行符分隔的单个字符串:

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);
}

这就去掉了另一层,例如:
// 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>"

现在我们可以将一个层级移出到“artists”数组中。就像我们从单个链接转移到“links”数组时一样,我们可以使用array_map处理内容并使用implode将它们连接在一起:
function render_artists($artists) {
  $rendered = array_map('render_artist', $artists);
  return implode("\n<br /><br />\n", $rendered);
}

这个已经移除了另一个层级(没有示例,因为它变得太长了 ;))

接下来我们有一个事件,我们可以用同样的方式解决艺术家问题,尽管我也会删除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);
}

现在我们已经到达了最外层的数组,即事件数组。我们可以像处理艺术家数组一样处理它:
function render_events($events) {
  $rendered = array_map('render_event', $events);
  return implode("\n<br /><br />--<br /><br />", $rendered);
}

你可能想要停在这里,因为将你的数组传递给render_events将返回你想要的HTML:
echo render_events($my_data);

然而,如果我们希望更有挑战性,我们可以尝试重构刚刚编写的代码,使其更少冗余并且更易于重复使用。其中一个简单的步骤是摆脱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);

如果这是一个较大应用的一部分,我们可能希望抽象出一些更通用的模式。这会让代码略微复杂些,但更具可重用性。以下是我发现的几个模式:

// 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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接