PHP将数组合并在相似元素上

4

我有一些数据是这种格式:

even--heaped<br />
even--trees<br />
hardrocks-cocked<br />
pebble-temple<br />
heaped-feast<br />
trees-feast<br />

我希望您最终得到的输出是所有具有相同单词的行被添加在一起,没有重复。
even--heaped--trees--feast<br />
hardrocks--cocked<br />
pebbles-temple<br />

我尝试了一个循环来遍历两个数组,但它并不是我想要的精确结果。对于一个名为$thing的数组:

Array ( [0] => even--heaped [1] => even--trees [2] => hardrocks--cocked [3] => pebbles--temple [4] => heaped--feast [5] => trees--feast )



for ($i=0;$i<count($thing);$i++){
    for ($j=$i+1;$j<count($thing);$j++){
        $first = explode("--",$thing[$i]);
        $second = explode("--",$thing[$j]);

        $merge = array_merge($first,$second);
        $unique = array_unique($merge);

    if (count($unique)==3){
        $fix = implode("--",$unique);
        $out[$i] = $thing[$i]."--".$thing[$j];
    }

}

}

print_r($out);

但是结果是:
Array ( [0] => even--heaped--heaped--feast [1] => even--trees--trees--feast [4] => heaped--feast--trees--feast )

这不是我想要的。有什么建议(对于可怕的变量名,我感到很抱歉)。


请提供 $thing 数组。 - user4035
数组([0] => even--heaped [1] => even--trees [2] => hardrocks--cocked [3] => pebbles--temple [4] => heaped--feast [5] => trees--feast) - user2426240
4个回答

3
这可能会对你有所帮助:
$in = array( 
    "even--heaped",
    "even--trees",
    "hardrocks--cocked",
    "pebbles--temple",
    "heaped--feast",
    "trees--feast"
);

$clusters = array();

foreach( $in as $item ) {

    $words = explode("--", $item);

    // check if there exists a word in an existing cluster...
    $check = false;
    foreach($clusters as $k => $cluster) {
        foreach($words as $word) {
            if( in_array($word, $cluster) ) {
                // add the words to this cluster
                $clusters[$k] = array_unique( array_merge($cluster, $words) );
                $check = true;
                break;
            }
        }
    }

    if( !$check ) {
        // create a new cluster
        $clusters[] = $words;
    }
}

// merge back
$out = array();
foreach( $clusters as $cluster ) {
    $out[] = implode("--", $cluster);
}

pr($out);

1
我使用了相同的方法,但是使用哈希表而不是数组。检查哈希键比每次迭代执行array_unique / array_merge更有效率。 - user4035

2

试试这段代码:

<?php
$data = array ("1--2", "3--1", "4--5", "2--6");

$n = count($data);
$elements = array();
for ($i = 0; $i < $n; ++$i)
{
      $split = explode("--", $data[$i]);
      $word_num = NULL;

      foreach($split as $word_key => $word)
      {
            foreach($elements as $key => $element)
            {
                  if(isset($element[$word]))
                  {
                        $word_num = $key;
                        unset($split[$word_key]);
                  }
             }

      }

      if(is_null($word_num))
      {
            $elements[] = array();
            $word_num = count($elements) - 1;
      }
      foreach($split as $word_key => $word)
      {
            $elements[$word_num][$word] = 1;
      }
}

//combine $elements into words
foreach($elements as $key => $value)
{
      $words = array_keys($value);
      $elements[$key] = implode("--", $words);
}

var_dump($elements);

它使用$elements作为哈希数组来存储各个独特的单词作为键。然后组合这些键来创建适当的单词。
打印如下:
array(2) {
  [0]=>
  string(10) "1--2--3--6"
  [1]=>
  string(4) "4--5"
}

@user2426240 通过使用 unset 而不是将元素标记为 NULL,稍微改进了答案。 - user4035

1
这是一个简单控制流的解决方案。
<?php
    $things = array('even--heaped', 'even--trees', 'hardrocks--cocked', 
        'pebble--temple', 'heaped--feast' ,'trees--feast');

    foreach($things as $thing) {
        $str = explode('--', $thing);
        $first = $str[0];
        $second = $str[1];
        $i = '0';
        while(true) {
            if(!isset($a[$i])) {
                $a[$i] = array();
                array_push($a[$i], $first);
                array_push($a[$i], $second);
                break;
            } else if(in_array($first, $a[$i]) && !in_array($second, $a[$i])) {
                array_push($a[$i], $second);
                break;
            } else if(!in_array($first, $a[$i]) && in_array($second, $a[$i])) {
                array_push($a[$i], $first);
                break;
            } else if(in_array($first, $a[$i]) && in_array($second, $a[$i])) {
                break;
            }
            $i++;
        }

    }
    print_r($a);
?>

1

看起来你已经选择了user4035的答案作为最佳答案。

但我认为这个更加优化(如果我错了,请纠正我):eval.in

代码:

$array = Array ( 'even--heaped' , 'even--trees' ,'hardrocks--cocked' , 'pebbles--temple' , 'heaped--feast' , 'trees--feast' );
print "Input: ";
print_r($array);

for($j=0;$j < count($array);$j++){
    $len = count($array);
    for($i=$j+1;$i < $len;$i++){
        $tmp_array = explode("--", $array[$i]);
        $pos1 = strpos($array[$j], $tmp_array[0]);
        $pos2 = strpos($array[$j], $tmp_array[1]);

        if (!($pos1 === false) && $pos2 === false){
            $array[$j] = $array[$j] . '--'.$tmp_array[1];unset($array[$i]);
        }elseif(!($pos2 === false) && $pos1 === false){
            $array[$j] = $array[$j] . '--'.$tmp_array[0];unset($array[$i]);
        }elseif(!($pos2 === false) && !($pos1 === false)){
            unset($array[$i]);
        }
    }
    $array = array_values($array);
}

print "\nOutput: ";
print_r($array);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接