PHP: 如何比较嵌套关联数组中的值?
PHP: How do I compare values in nested associative arrays?
我正在思考如何实现这一点……
我有一个类似的东西:
$contributors = array(
[0] => array(
[name] => 'John',
[role] => 'author',
),
[1] => array(
[name] => 'Gail',
[role] => 'author',
),
[2] => array(
[name] => 'Beth',
[role] => 'illustrator',
),
)
我正在尝试使用此信息来构建详细的署名,例如:
Written by John and Gail. Designed by Beth.
我需要将每个 role
与前一个和下一个进行比较,以便:
- 在每个
role
的第一个实例之前使用标签
- 用逗号
分隔相同role
的多个实例
- 在每个
role
的最后一个实例之前使用 "and" 而不是逗号
我不是 PHP 专家,所以我很难弄清楚如何解决这个问题!我有一个函数可以根据 role
输出正确的标签,但这是我似乎无法弄清楚的比较。我考虑过 foreach
和 while
循环,但似乎都不能胜任。我从未使用过 for
循环,所以我不知道它是否适用。
一些额外的背景:
- 我正在使用 WordPress 和高级自定义字段插件。
$contributors
是 ACF Repeater 字段的值,其中 name
和 role
是子字段。 (为了方便起见,我简化了名称。)
您可以按角色对数组进行分组,然后使用 array_pop
删除元素。 implode
剩余的数组元素并仅附加 弹出的值。
$contributors = array(
array(
"name" => 'John',
"role" => 'author',
),
array(
"name" => 'Gail',
"role" => 'author',
),
array(
"name" => 'Jose',
"role" => 'author',
),
array(
"name" => 'Thomas',
"role" => 'author',
),
array(
"name" => 'Beth',
"role" => 'illustrator',
),
array(
"name" => 'Mary',
"role" => 'producer',
),
array(
"name" => 'Criss',
"role" => 'producer',
),
);
//Grouped the names according to role
$grouped = array_reduce($contributors, function($c, $v) {
if ( !isset( $c[ $v['role'] ] ) ) $c[ $v['role'] ] = array();
$c[ $v['role'] ][] = $v['name'];
return $c;
}, array());
//Construct final Array
$final = array();
foreach( $grouped as $key => $group ) {
$last = array_pop( $group );
if ( count( $group ) == 0 ) $final[ $key ] = $last; /* One one name on the role, no need to do anything*/
else $final[ $key ] = implode( ", ", $group ) . " and " . $last;
}
echo "<pre>";
print_r( $final );
echo "</pre>";
这将导致:
Array
(
[author] => John, Gail, Jose and Thomas
[illustrator] => Beth
[producer] => Mary and Criss
)
您现在可以将其用作
echo 'Written by ' . $final["author"] . '. Designed by ' . $final["illustrator"] . '. Produced by ' . $final["producer"];
结果为:
Written by John, Gail, Jose and Thomas. Designed by Beth. Produced by
Mary and Criss
你可以这样试试-
$contributors = array(
array(
'name' => 'John',
'role' => 'author',
),
array(
'name' => 'Gail',
'role' => 'author',
),
array(
'name' => 'Ali',
'role' => 'author',
),
array(
'name' => 'Beth',
'role' => 'illustrator',
)
);
#This function prepare array to expected String
function PrepareArray($data){
$combined = '';
if (count($data)>1) {
$last = array_slice($data, -1);
$first = join(', ', array_slice($data, 0, -1));
$both = array_filter(array_merge(array($first), $last), 'strlen');
$combined = join(' and ', $both);
}else{
$combined = implode('', $data);
}
return $combined;
}
$authors = array();
$designers = array();
foreach ($contributors as $key => $value) {
if ($value['role']=='author') {
$authors[] = $value['name']; #Keep Authors name in Array
}else if ($value['role']=='illustrator') {
$designers[] = $value['name']; #Keep Designers name in Array
}
}
$authors = PrepareArray($authors);
$designers = PrepareArray($designers);
echo "Written by {$authors}. Designed by {$designers}.";
输出:
Written by John, Gail and Ali. Designed by Beth.
试试下面的代码:
<?php
$contributors = array(
0 => array(
'name' => 'John',
'role' => 'author',
),
1 => array(
'name' => 'Gail',
'role' => 'author',
),
2 => array(
'name' => 'Beth',
'role' => 'illustrator',
),
3 => array(
'name' => 'Albert',
'role' => 'author',
),
);
$labels = ['author'=>'Written by', 'illustrator'=>'Designed by', 'producer'=>'Produced by'];
$new_contributors = [];
foreach($contributors as $cont){
$new_contributors[$cont['role']][] = $cont['name'];
}
$str = '';
foreach($labels as $role=>$label){
if(isset($new_contributors[$role]) && is_array($new_contributors[$role])){
$str .= ' '.$label.' ';
foreach($new_contributors[$role] as $key=>$new_contributor){
$count = count($new_contributors[$role]);
if(($count - $key) == 1 ){
$str .= ' and ';
$str .= $new_contributor;
}else if(($count - $key) == 2){
$str .= $new_contributor;
}else{
$str .= $new_contributor.', ';
}
}
}
}
echo $str;
我正在思考如何实现这一点……
我有一个类似的东西:
$contributors = array(
[0] => array(
[name] => 'John',
[role] => 'author',
),
[1] => array(
[name] => 'Gail',
[role] => 'author',
),
[2] => array(
[name] => 'Beth',
[role] => 'illustrator',
),
)
我正在尝试使用此信息来构建详细的署名,例如:
Written by John and Gail. Designed by Beth.
我需要将每个 role
与前一个和下一个进行比较,以便:
- 在每个
role
的第一个实例之前使用标签
- 用逗号 分隔相同
- 在每个
role
的最后一个实例之前使用 "and" 而不是逗号
role
的多个实例
我不是 PHP 专家,所以我很难弄清楚如何解决这个问题!我有一个函数可以根据 role
输出正确的标签,但这是我似乎无法弄清楚的比较。我考虑过 foreach
和 while
循环,但似乎都不能胜任。我从未使用过 for
循环,所以我不知道它是否适用。
一些额外的背景:
- 我正在使用 WordPress 和高级自定义字段插件。
$contributors
是 ACF Repeater 字段的值,其中name
和role
是子字段。 (为了方便起见,我简化了名称。)
您可以按角色对数组进行分组,然后使用 array_pop
删除元素。 implode
剩余的数组元素并仅附加 弹出的值。
$contributors = array(
array(
"name" => 'John',
"role" => 'author',
),
array(
"name" => 'Gail',
"role" => 'author',
),
array(
"name" => 'Jose',
"role" => 'author',
),
array(
"name" => 'Thomas',
"role" => 'author',
),
array(
"name" => 'Beth',
"role" => 'illustrator',
),
array(
"name" => 'Mary',
"role" => 'producer',
),
array(
"name" => 'Criss',
"role" => 'producer',
),
);
//Grouped the names according to role
$grouped = array_reduce($contributors, function($c, $v) {
if ( !isset( $c[ $v['role'] ] ) ) $c[ $v['role'] ] = array();
$c[ $v['role'] ][] = $v['name'];
return $c;
}, array());
//Construct final Array
$final = array();
foreach( $grouped as $key => $group ) {
$last = array_pop( $group );
if ( count( $group ) == 0 ) $final[ $key ] = $last; /* One one name on the role, no need to do anything*/
else $final[ $key ] = implode( ", ", $group ) . " and " . $last;
}
echo "<pre>";
print_r( $final );
echo "</pre>";
这将导致:
Array
(
[author] => John, Gail, Jose and Thomas
[illustrator] => Beth
[producer] => Mary and Criss
)
您现在可以将其用作
echo 'Written by ' . $final["author"] . '. Designed by ' . $final["illustrator"] . '. Produced by ' . $final["producer"];
结果为:
Written by John, Gail, Jose and Thomas. Designed by Beth. Produced by Mary and Criss
你可以这样试试-
$contributors = array(
array(
'name' => 'John',
'role' => 'author',
),
array(
'name' => 'Gail',
'role' => 'author',
),
array(
'name' => 'Ali',
'role' => 'author',
),
array(
'name' => 'Beth',
'role' => 'illustrator',
)
);
#This function prepare array to expected String
function PrepareArray($data){
$combined = '';
if (count($data)>1) {
$last = array_slice($data, -1);
$first = join(', ', array_slice($data, 0, -1));
$both = array_filter(array_merge(array($first), $last), 'strlen');
$combined = join(' and ', $both);
}else{
$combined = implode('', $data);
}
return $combined;
}
$authors = array();
$designers = array();
foreach ($contributors as $key => $value) {
if ($value['role']=='author') {
$authors[] = $value['name']; #Keep Authors name in Array
}else if ($value['role']=='illustrator') {
$designers[] = $value['name']; #Keep Designers name in Array
}
}
$authors = PrepareArray($authors);
$designers = PrepareArray($designers);
echo "Written by {$authors}. Designed by {$designers}.";
输出:
Written by John, Gail and Ali. Designed by Beth.
试试下面的代码:
<?php
$contributors = array(
0 => array(
'name' => 'John',
'role' => 'author',
),
1 => array(
'name' => 'Gail',
'role' => 'author',
),
2 => array(
'name' => 'Beth',
'role' => 'illustrator',
),
3 => array(
'name' => 'Albert',
'role' => 'author',
),
);
$labels = ['author'=>'Written by', 'illustrator'=>'Designed by', 'producer'=>'Produced by'];
$new_contributors = [];
foreach($contributors as $cont){
$new_contributors[$cont['role']][] = $cont['name'];
}
$str = '';
foreach($labels as $role=>$label){
if(isset($new_contributors[$role]) && is_array($new_contributors[$role])){
$str .= ' '.$label.' ';
foreach($new_contributors[$role] as $key=>$new_contributor){
$count = count($new_contributors[$role]);
if(($count - $key) == 1 ){
$str .= ' and ';
$str .= $new_contributor;
}else if(($count - $key) == 2){
$str .= $new_contributor;
}else{
$str .= $new_contributor.', ';
}
}
}
}
echo $str;