使用 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;
}
}
我需要帮助编写 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;
}
}