4

I have some data in this format:

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

and I want to end up with an output so that all lines with the same words get added to each other with no repeats.

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

i tried a loop going through both arrays but its not the exact result I want. for an array $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);

but the result is:

Array ( [0] => even--heaped--heaped--feast [1] => even--trees--trees--feast [4] => heaped--feast--trees--feast )

which is not what i want. Any suggestions (sorry about the terrible variable names).

2
  • please, provide $thing array Commented May 27, 2013 at 20:57
  • Array ( [0] => even--heaped [1] => even--trees [2] => hardrocks--cocked [3] => pebbles--temple [4] => heaped--feast [5] => trees--feast ) Commented May 27, 2013 at 21:03

4 Answers 4

3

This might help you:

$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);
Sign up to request clarification or add additional context in comments.

1 Comment

I used the same approach, but a hash instead of array. Checking hash keys is more efficient, then doing array_unique / array_merge for each iteration.
2

Try this code:

<?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);

It uses $elements as an array of hashes to store the individual unique words as keys. Then combines the keys to create appropriate words.

Prints this:

array(2) {
  [0]=>
  string(10) "1--2--3--6"
  [1]=>
  string(4) "4--5"
}

1 Comment

@user2426240 improved the answer a little bit by using unset instead of marking element as NULL
1

Here is a solution with a simple control flow.

<?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);
?>

Comments

1

It seems you have already selected user4035's answer as best.

But i feel this one is optimized(Please correct me if i am wrong): eval.in

Code:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.