使用 php 对相似记录进行分组

Grouping similar records with php

我需要帮助编写 php 脚本的逻辑,该脚本将数据排序为特定格式...

首先,脚本需要遍历每个 s1 值并 ping 一个端点以获取实际上引用其他 s1 记录的 ml 值(更像是)。这是简单的部分!数据是这样返回的;

Table 1
s1  |   ml
----------
1   |   -
2   |   3,4    
3   |   2,8,9
4   |   -
5   |   2
6   |   1
7   |   10
8   |   -
9   |   -
10  |   -

条件1:正如你所看到的端点returns s1值的数据告诉它其他s1记录与其他s1记录相似,但ml的方向并不总是双向的。有时,比如当 s1=6 时,ml 值为 1,但是当 s1=1 时,没有 ml 值。

条件 2: 再次解释 ml 记录,查看上方和下方 where s1=5(上方)和 where s1=2 + rec=5(下方),这个脚本需要意识到已经有一个 s1 记录作为它的值,并且应该将它添加到那里。

条件 3: 注意当 s1=2,ml=3 时,这是如何存储的,而当 s1=3,ml=2 时,这是如何被忽略的,因为我们有反向记录。

我基本上想将所有数据匹配到 1 个排序的 'profile' 中,所以它以下面的格式结束,我将存储在 'sorted' 记录的另一个数据库 table 中。

Table 2
s1  |   rec
----------
2   |   3
2   |   4
2   |   8
2   |   9
2   |   9
2   |   5
6   |   1
7   |   10

这几天一直在绞尽脑汁,我需要一些高效的东西,因为最终它会处理数百万条记录,我相信有一个简单的解决方案,但我就是不知道如何去做开始吧。

我尝试了以下方法,但卡住了,不知道如何继续;

public function getrelated($id='', $t=''){

    if($id != ""){
    $get = Easytest::where('s1','=',$id)->get();

        if(count($get) > 0){
            $ret= array();
            foreach($get as $go){
                    $v = explode(",", $go->s2);

                    foreach ($v as $e) {
                        if($e != $t){
                            $ret[$e] = $this->getrelated($e, $id);
                        }
                    }
                }
                if(count($ret) > 0){
                    return $ret;
                }else{
                    return "";
                }

        }else{
                return $id;
        }
     }else{
        return "";
     }

     }

public function easytest(){
    ob_start();
    $a = array(
                array("s1"=>1,"s2"=>implode(",",array()).""),
                array("s1"=>2,"s2"=>implode(",",array(3,4)).","),
                array("s1"=>3,"s2"=>implode(",",array(2,8,9)).","),
                array("s1"=>4,"s2"=>implode(",",array()).""),
                array("s1"=>5,"s2"=>implode(",",array(2)).","),
                array("s1"=>6,"s2"=>implode(",",array(1)).","),
                array("s1"=>7,"s2"=>implode(",",array(10)).","),
                array("s1"=>8,"s2"=>implode(",",array()).""),
                array("s1"=>9,"s2"=>implode(",",array()).""),
                array("s1"=>10,"s2"=>implode(",",array()).""),
                array("s1"=>11,"s2"=>implode(",",array(12)).","),
                array("s1"=>12,"s2"=>implode(",",array(2)).",")
                );

    //return Easytest::insert($a);

    $records = Easytest::all();

    foreach ($records as $record) {

        $id = $record->s1;
        echo "ROW: ".$id." > ";
        $record->s2 = ltrim($record->s2,",");
        $ml = explode(",",$record->s2);
        if(count($ml) >= 1){
            foreach ($ml as $t) {

                echo "RESULT: ".$t." -".print_r($this->getrelated($t, $id), true);
                echo ",\n";

            }
        }
        echo " <br><br>\n\n";

    }

    return ob_get_clean();

}

好的,所以我最终解决了这个问题……基本上这是下面的代码; 欢迎改进:)

你需要像这样调用函数

related(array('searched'=>array(),'tosearch'=>array(13)));

函数:

public function related($input){


    $searched = $input['searched'];

    $ar = array();
    $bits = array();

    if(count($input['tosearch']) != 0){

        $get = Easytest::orWhere(function($query) use ($input)
                        {
                            foreach ($input['tosearch'] as $k=>$v) {
                                    $query->orWhere('s2', 'LIKE', '%,'.$v.',%')->orWhere('s1', '=', $v);
                                }                      
                        })
            ->orderBy('s1', 'ASC')->get();

            foreach ($input['tosearch'] as $k=>$v) {
                                unset($input['tosearch'][$k]);
                                $input['searched'][$v] = $v;
                }


            foreach ($get as $result) {

                $thesebits = explode(",", trim($result->s2,","));
                foreach ($thesebits as $smallbit) {
                    if($smallbit != ""){
                    $bits[] = $smallbit;
                    }
                }

                $bits[] = $result->s1;
                $bits = array_unique($bits);

                foreach ($bits as $k=>$v) {
                        if(($key = array_search($v, $input['searched'])) == false) {
                                $input['tosearch'][$v] = $v; 
                        }else{
                            unset($input['tosearch'][$v]);
                        }

                }

                $input['tosearch'] = array_unique($input['tosearch']);

            }
            return $this->related($input);
    }else{
        return $input;
    }

}