0

我有一些学生参加了课程。有多个重复,每门课程应该只有一个学生。

示例数组:

'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 删除项目。

进一步的限制:

  • 我无法控制 API。
  • 有 44,000 条记录
  • 每人 + 课程可能有多达 100 个重复项
  • API 返回对象的嵌套层次结构,因此 44,000 条记录使用 27GB 的 RAM(服务器有 144GB 可使用),是的 php_memory 限制设置为荒谬的水平!!!这是一个单独的项目,之后将采取措施更正服务器变量。
  • 由于大量的 RAM 使用,诸如 array_intersect 之类的东西将是一个不太受欢迎的选择

最终输出应该是:

    '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's 3,4,6 以便我可以通过 API 调用删除例程。

任何想法如何解决这个多重重复的混乱?

4

2 回答 2

1

看起来您正试图通过同时解析所有项目来解决XY 问题,而实际上您只需要阅读有关Podio API以及如何使用 PodioObjects 使用其 API 的信息。

因此,不是遍历整个数组,PodioItemCollection而是通过键字段(例如)对对象进行排序来遍历对象(在这种情况下)student,例如:

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

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

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

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

也可以看看:

于 2015-09-10T10:50:49.043 回答
0

以下功能将为您完成工作:

$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
        )

)    
于 2015-09-10T01:48:10.263 回答