我有一个asosiative数组,其中包含有关球队和球员的数据。
示例:
$arr = array(
array('teamID'=> '','teamName' => 'USA', 'playerName'='John'),
array('teamID'=> '','teamName' => 'USA', 'playerName'='Peter'),
array('teamID'=> '12','teamName' => 'Norway', 'playerName'='Zigmund'),
array('teamID'=> '','teamName' => 'USA', 'playerName'='Parker'),
array('teamID'=> '','teamName' => 'Norway', 'playerName'='Jan'),
array('teamID'=> '','teamName' => 'USA', 'playerName'='Hector'),
array('teamID'=> '','teamName' => 'Germany', 'playerName'='Alexander'),
array('teamID'=> '','teamName' => 'Slovakia', 'playerName'='Ivan')
);
如果每个团队不存在,我想为每个团队生成唯一ID,如果某个团队的ID存在,如果他们不存在,则使用相同的团队名称,并且不使用已经存在的id' s
我所做的是简单检查一下foreach循环的广告索引是否存在,然后是每个玩家而不是每个团队。
预期结果:
$arr = array(
array('teamID'=> '1','teamName' => 'USA', 'playerName='John'),
array('teamID'=> '1','teamName' => 'USA', 'playerName'='Peter'),
array('teamID'=> '12','teamName' => 'Norway', 'playerName'='Zigmund'),
array('teamID'=> '1','teamName' => 'USA', 'playerName'='Parker'),
array('teamID'=> '12','teamName' => 'Norway', 'playerName'='Jan'),
array('teamID'=> '1','teamName' => 'USA', 'playerName'='Hector'),
array('teamID'=> '2','teamName' => 'Germany', 'playerName'='Alexander'),
array('teamID'=> '3','teamName' => 'Slovakia', 'playerName'='Ivan')
);
关于如何解决这个问题的任何想法?
答案 0 :(得分:1)
这将解决您的问题(作为众多可能的解决方案之一)。 这里我们有一个数组,将每个团队名称作为一个键,并为每个团队名称的每个出现增加一个数字ID。然后我们检查密钥是否存在,如果存在,我们重用分配给它的ID。如果它不存在,我们创建它并添加一个ID,然后递增整数。
$teams_with_ids = [];
$teamids = [];
$i=0;
foreach( $arr AS $team ){
if( array_key_exists($team['teamName'], $teamids) ){
$team['teamID'] = $teamids[$team['teamName']];
} else {
$teamids[$team['teamName']] = $i;
$team['teamID'] = $i;
$i++;
}
array_push($teams_with_ids, $team);
}
修改强>
正如评论中所指出的,上述解决方案并未考虑某些团队的现有ID。这样做:
$teams_with_ids = [];
$teamids = [];
$existing_ids = array_filter((array_map(function($team){ if( !empty( $team['teamID'] ) ) return intval($team['teamID']); },$arr)));
$i=0;
foreach( $arr AS $team ){
if( array_key_exists($team['teamName'], $teamids) ){
$team['teamID'] = $teamids[$team['teamName']];
} else {
if( in_array( $i, $existing_ids ) ) $i++; // Adding +1 to $i since the ID is already taken
$teamids[$team['teamName']] = (!empty($team['teamID']) && in_array($team['teamID'], $existing_ids)) ? $team['teamID'] : $i;
$team['teamID'] = (empty($team['teamID'])) ? $i : $team['teamID'];
if( empty($team['teamID'] ) ) $i++;
}
array_push($teams_with_ids, $team);
}
答案 1 :(得分:0)
这直接操纵原始数组并添加“缺失”ID:
$teams = [];
$id_counter = 1;
$teamids = [];
foreach($arr as $entry) {
$teamids[] = $entry['teamID'];
}
array_unique($teamids);
foreach($arr as &$entry) {
if(!isset($teams[$entry['teamName']])) {
if($entry['teamID'] == '') {
while(in_array($id_counter, $teamids)) {
$id_counter++;
}
$teamids[] = $id_counter;
array_unique($teamids);
$teams[$entry['teamName']] = $id_counter;
}
else {
$teams[$entry['teamName']] = $entry['teamID'];
$teamids[] = $entry['teamID'];
array_unique($teamids);
}
}
$entry['teamID'] = $teams[$entry['teamName']];
}
unset($entry);
答案 2 :(得分:0)
我认为正确的解决方案就是这个 - 我试过的其他工作都没有按预期进行。
$arr = array(
array('teamID'=> '', 'teamName' => 'USA', 'playerName'=>'John'),
array('teamID'=> '', 'teamName' => 'USA', 'playerName'=>'Peter'),
array('teamID'=> '12', 'teamName' => 'Norway', 'playerName'=>'Zigmund'),
array('teamID'=> '', 'teamName' => 'USA', 'playerName'=>'Parker'),
array('teamID'=> '', 'teamName' => 'Norway', 'playerName'=>'Jan'),
array('teamID'=> '', 'teamName' => 'USA', 'playerName'=>'Hector'),
array('teamID'=> '', 'teamName' => 'Germany', 'playerName'=>'Alexander'),
array('teamID'=> '', 'teamName' => 'Slovakia', 'playerName'=>'Ivan'),
);
function getTeamIdFromName($arr, $teamName){
foreach($arr as $element){
if($element["teamName"] == $teamName && !empty($element["teamID"])){
return $element["teamID"];
}
}
return false;
}
function getNewTeamId($arr){
$existingIds = array_unique(array_column($arr, 'teamID'));
$id = 1;
while(in_array($id, $existingIds)) $id++;
return $id;
}
foreach($arr as $k=>$element){
if(empty($element['teamId'])){
if(!($id = getTeamIdFromName($arr, $element["teamName"]))){
$id = getNewTeamId($arr);
}
$arr[$k]['teamID'] = $id;
}
}
请注意,您应该为数组键和“>”使用引号对于失踪的球员姓名。
答案 3 :(得分:0)
为避免在遍历输入数组时对teamID
值执行迭代查找,最佳做法是先/单独生成查找数组。
创建查找数组肯定比应用它更繁琐。我已经评论了临时数组值,以帮助您了解每一步生成的内容。使用相关的变量名和数组函数(提高代码理解能力),我认为不应该太难理解。
对于那些无法比较代码性能的人,MarcusKreusch的答案是目前唯一能够提供正确结果的答案。但是,它在输入数组的每次迭代中对输入数组进行两次扫描(在自定义函数调用内)。我的解决方案更直接,更有效,因为它使用更少的迭代函数调用/循环/条件。
代码:(Demo)
$lookup=array_column($arr,'teamID','teamName'); // var_export($lookup); // ['USA'=>'','Norway'=>'','Germany'=>'','Slovakia'=>'']
$positive_ids=array_filter(array_flip(array_column($arr,'teamName','teamID'))); // var_export($positive_ids); // ['Norway'=>12]
$i=0;
foreach($lookup as $name=>&$id){
if(isset($positive_ids[$name])){
$id=$positive_ids[$name];
}else{
while(in_array(++$i,$positive_ids)); // avoid collisions between existing and new ids
$id=$i;
}
} // var_export($lookup); // ['USA'=>1,'Norway'=>12,'Germany'=>2,'Slovakia'=>3]
foreach($arr as &$row){
$row['teamID']=$lookup[$row['teamName']]; // make id assignments
}
结果:(修改后的$arr
现在包含...)
array(
array('teamID'=> 1,'teamName' => 'USA', 'playerName'=>'John'),
array('teamID'=> 1,'teamName' => 'USA', 'playerName'=>'Peter'),
array('teamID'=> 12,'teamName' => 'Norway', 'playerName'=>'Zigmund'),
array('teamID'=> 1,'teamName' => 'USA', 'playerName'=>'Parker'),
array('teamID'=> 12,'teamName' => 'Norway', 'playerName'=>'Jan'),
array('teamID'=> 1,'teamName' => 'USA', 'playerName'=>'Hector'),
array('teamID'=> 2,'teamName' => 'Germany', 'playerName'=>'Alexander'),
array('teamID'=> 3,'teamName' => 'Slovakia', 'playerName'=>'Ivan')
)
我想澄清一下,我的解决方案适当地处理了两个可能且麻烦的输入数组:
问题:增加的ID中的差距
$arr = array(
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'John'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Peter'),
array('teamID'=> '','teamName' => 'Norway', 'playerName'=>'Zigmund'),
array('teamID'=> '','teamName' => 'Slovakia', 'playerName'=>'Ivan'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Parker'),
array('teamID'=> '12','teamName' => 'Norway', 'playerName'=>'Jan'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Hector'),
array('teamID'=> '','teamName' => 'Germany', 'playerName'=>'Alexander')
);
仔细检查后,您会看到第一次出现的Norway
没有ID。循环数组以分配新密钥的任何方法都会认为Norway
需要增加id
。由于Norway
位于USA
之后(声称为1
),因此Norway
的ID为2
。然后Slovakia
被赋予3
。然后id
的{{1}}被覆盖为Norway
。最后,12
被赋予Germany
。这会在增量中留下空白。
问题:现有ID和新ID之间的冲突
4
如果没有检查ID冲突,上面的数组将生成两个以$arr = array(
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'John'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Peter'),
array('teamID'=> '2','teamName' => 'Norway', 'playerName'=>'Zigmund'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Parker'),
array('teamID'=> '','teamName' => 'Norway', 'playerName'=>'Jan'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Hector'),
array('teamID'=> '','teamName' => 'Germany', 'playerName'=>'Alexander'),
array('teamID'=> '','teamName' => 'Slovakia', 'playerName'=>'Ivan')
);
作为ID的团队。
答案 4 :(得分:-1)
不是最好的方式,但有效:
$arr = array(
array('teamID' => '', 'teamName' => 'USA', 'playerName' => 'John'),
array('teamID' => '', 'teamName' => 'USA', 'playerName' => 'Peter'),
array('teamID' => '12', 'teamName' => 'Norway', 'playerName' => 'Zigmund'),
array('teamID' => '', 'teamName' => 'USA', 'playerName' => 'Parker'),
array('teamID' => '4', 'teamName' => 'Norway', 'playerName' => 'Jan'),
array('teamID' => '', 'teamName' => 'USA', 'playerName' => 'Hector'),
array('teamID' => '', 'teamName' => 'Germany', 'playerName' => 'Alexander'),
array('teamID' => '', 'teamName' => 'Slovakia', 'playerName' => 'Ivan'),
);
// build array with existing ids
$ids = array();
foreach ($arr as $row) {
if ($row['teamID'] !== '') {
$ids []= $row['teamID'];
}
}
// start from
$id = 1;
foreach ($arr as $i => $row) {
if ($row['teamID'] === '') {
while(in_array($id, $ids)) {
$id++;
}
// put id in $arr
$arr[$i]['teamID'] = $id;
$id++;
}
}
var_dump($arr);