如何在 PodioItemCollection 响应中找到多个重复项?

How to find multiple duplicates in a PodioItemCollection response?

我有一个数组,其中有一些已注册课程的学生。有多个重复项,每个课程应该只有一个学生。

示例数组:

'item_id'=> 1, 'student'=> 'Bob', 'course'=> 'Learn Piano', 'address'=>''
'item_id'=> 2, 'student'=> 'Sam', 'course'=> 'Learn Piano', 'address'=> 'foo street'
'item_id'=> 3, 'student'=> 'Bob', 'course'=> 'Learn Guitar', 'address'=>''
'item_id'=> 4, 'student'=> 'Sam', 'course'=> 'Learn Piano', 'address'=>''
'item_id'=> 5, 'student'=> 'Bob', 'course'=> 'Learn Guitar', 'address'=> 'bla bla street'
'item_id'=> 6, 'student'=> 'Sam', 'course'=> 'Learn Piano', 'address'=>''
'item_id'=> 7, 'student'=> 'John', 'course'=> 'Learn Guitar', 'address'=>''

通过 API 访问数据(否则整个事情将是一个简单的 SQL 查询!)。

原始数据如下所示:

object(PodioItemCollection)#287 (5) { ["filtered"]=> int(45639) ["total"]=> int(45639) ["items"]=> NULL ["__items":"PodioCollection":private]=> array(10) { [0]=> object(PodioItem)#3 (5) { ["__attributes":"PodioObject":private]=> array(16) { ["item_id"]=> int(319357433) ["external_id"]=> NULL ["title"]=> string(12) "Foo Bar" ["link"]=> string(71) "https://podio.com/foo/enrolments/apps/applications/items/123" ["rights"]=> array(11) ...

挑战是我不能只使用 array_unique 或类似的,因为我需要:

  1. 查找学生 + 课程的所有重复项
  2. 相互比较找到的重复项并保留具有最多补充信息的项目(或合并它们)
  3. 获取重复项不需要的 "item_id" 并使用 API 删除项目。

进一步限制:

最终输出应该是:

    'item_id'=> 1, 'student'=> 'Bob', 'course'=> 'Learn Piano', 'address'=>''
    'item_id'=> 2, 'student'=> 'Sam', 'course'=> 'Learn Piano', 'address'=> 'foo street'
    'item_id'=> 5, 'student'=> 'Bob', 'course'=> 'Learn Guitar', 'address'=> 'bla bla street'
    'item_id'=> 7, 'student'=> 'John', 'course'=> 'Learn Guitar', 'address'=>''

但我还需要访问“item_id”的 3、4、6 以便我可以通过 API.

调用删除例程

有什么想法可以解决这个多重复的问题吗?

以下函数将为您完成这项工作:

$apiData = array(
   array('item_id'=> 1, 'student'=> 'Bob', 'course'=> 'Learn Piano', 'address'=>''),
   array('item_id'=> 2, 'student'=> 'Sam', 'course'=> 'Learn Piano', 'address'=> 'foo street'),
   array('item_id'=> 3, 'student'=> 'Bob', 'course'=> 'Learn Guitar', 'address'=>''),
   array('item_id'=> 4, 'student'=> 'Sam', 'course'=> 'Learn Piano', 'address'=>''),
   array('item_id'=> 5, 'student'=> 'Bob', 'course'=> 'Learn Guitar', 'address'=> 'bla bla street'),
   array('item_id'=> 6, 'student'=> 'Sam', 'course'=> 'Learn Piano', 'address'=>''),
   array('item_id'=> 7, 'student'=> 'John', 'course'=> 'Learn Guitar', 'address'=>'')
);

function resolveDuplicate($apiData = null)
{
  if(!$apiData) return false;

  foreach ($apiData as $key => $arr) {
    $key = $arr['student'] . ':' . $arr['course'];
    if(!$newArr[$key]['address']){
       if($newArr[$key]) $itemIds[] = $newArr[$key]['item_id'];
       $newArr[$key] = $arr;
    }
    else{
       $itemIds[] = $arr['item_id'];
    }
  }

  if($newArr){
     foreach ($newArr as $value) {
       $finalArr[] = $value;
     }
  }

  $result['student']    = $finalArr;
  $result['duplicates'] = $itemIds;
  return $result;
}

$res = resolveDuplicate($apiData);
echo '<pre>';
print_r($res);

输出

Array
(
    [student] => Array
        (
            [0] => Array
                (
                    [item_id] => 1
                    [student] => Bob
                    [course] => Learn Piano
                    [address] => 
                )

            [1] => Array
                (
                    [item_id] => 2
                    [student] => Sam
                    [course] => Learn Piano
                    [address] => foo street
                )

            [2] => Array
                (
                    [item_id] => 5
                    [student] => Bob
                    [course] => Learn Guitar
                    [address] => bla bla street
                )

            [3] => Array
                (
                    [item_id] => 7
                    [student] => John
                    [course] => Learn Guitar
                    [address] => 
                )

        )

    [duplicates] => Array
        (
            [0] => 4
            [1] => 3
            [2] => 6
        )

)    

您似乎在尝试修复 XY problem by parsing all the items at the same time, when actually you just need to read about Podio API 以及如何使用 PodioObjects API.

所以不是遍历整个数组,而是遍历对象(在本例中为PodioItemCollection),通过键字段(例如student)对其进行排序,例如:

PodioItem::filter(31060, array('limit' => 20, 'offset' => 20, 'sort_by' => 'student'));

然后(假设排序标准)您知道如果有一些重复项(学生 + 课程),它们是连续的。因此,只要你在下一行中有相同的学生姓名,就将其视为重复并忽略其他行(除非你想将它们作为当前学生对象的一部分进行处理),然后转到下一项。

在这种情况下,您可以避免同时处理所有记录,因此不会有任何内存问题。

如果内存问题仍然是个问题,使用NOSQL解决方案,如memcached或redis,将解析的项目存储在内存中,释放PHP中的变量,转到下一个,最后检查一致性(例如计算项目)。还请考虑禁用您拥有的任何额外 PHP 扩展,这些扩展可能会减慢处理速度(例如 xdebug 和类似的)。

另请参阅: