How to convert matrix?

I have an array like this:


$start = array(
   array('a', 'b', 'c'),
   array('b', 'c'),
   array('a', 'c')
);
 

and I want convert to:


$end = array(
   array('a' => 1, 'b' => 1, 'c' => 1),
   array('a' => 0, 'b' => 1, 'c' => 1),
   array('a' => 1, 'b' => 0, 'c' => 1)
);

It means that each element in $start will be key in $end. If key appears in $start, value is 1 and 0 if not. What do all you think?

Hi there,

Here’s my solution.
I’m still learning PHP (normally I work in Ruby), so I would be really grateful for any constructive criticism / pointers the rest of you could give me.

<?php
function convertArray($start){
  $end = array();
  $unique_keys = array();

  // Get a list of all possible keys
  for ($row = 0; $row < count($start); $row++){
    for ($col = 0; $col < count($start[$row]); $col++){
      array_push($unique_keys, $start[$row][$col]);
    }
  }
  $unique_keys = array_unique($unique_keys);
  sort($unique_keys);

  // Create new array using these keys
  for ($row = 0; $row < count($start); $row++){
    for ($col = 0; $col < count($start[$row]); $col++){
      $temp_array = array();
      foreach ($unique_keys as $key){
        $temp_array[$key] = in_array($key, $start[$row])? '1' : '0';
      }
    }
    array_push($end, $temp_array);
  }
  return($end);
}


$start = array(
   array('a', 'b', 'c'),
   array('b', 'c'),
   array('a', 'c')
);

print_r(convertArray($start));

This outputs:

Array ( [0] => Array ( [a] => 1 [b] => 1 [c] => 1 ) [1] => Array ( [a] => 0 [b] => 1 [c] => 1 ) [2] => Array ( [a] => 1 [b] => 0 [c] => 1 ) )

Do you know for sure that $start (or $end) will always contain a fixed set of keys/values? Or a set of fixed keys/values you can divine/compute?

Hi! I’m still learning PHP too. Your solution is good. Thank a lot!

$start (or $end) is not contain a fixed set of keys and values, it’s based on database. Each subarray is a transaction (or an order).

And here is my solution:

main.php


for($i=0; $<count($database); $i++){
     $transaction[] = getTransaction($candidates, $database);
}


<?php
	function minus_sets($a, $b){
		
		// number candidates in database
		$number_cans = count($a);
		// number transactions database
		$number_trans = count($b);
		
		for($i=0; $i<count($a); $i++){
			$same= 0;
			for($j=0; $j<count($b); $j++){
				if($a[$i]==$b[$j]) $same= 1;
			}
			
			if(!$same){
				$tmp = $tmp + 1;
				$c[$tmp-1] = $a[$i];
			}
		}
		
		return $c;
	}
	
	//demo
	//$a = array(1, 2, 3, 4);
	//$b = array(2, 3, 4);
	//$minus = minus_set($a, $b);
	//print_r($minus);
	//result is Array ( [0] => 1 )
?>


<?php

	include('minus_sets.php');
	
	function getTransaction($candidates, $database){
		// $candidates minus $database to take elements not in $database
		$tmp = minus_sets($candidates, $database);
		
		for($i=0; $i<count($candidates); $i++){
			if(!in_array($candidates[$i], $tmp)){
				$transaction[$candidates[$i]] = 1;
			} else {
				$transaction[$candidates[$i]] = 0;
			}
		}
		
		return $transaction;
	}
	
	
	//$candidates = array('a', 'b', 'c', 'd', 'e');
	//$database = array('a', 'b', 'c');
	
	//$transaction = getTransaction($candidates, $database);
	//print_r($transaction);
// result is Array ( [a] => 1 [b] => 1 [c] => 1 [d] => 0 [e] => 0 )
?>

What do you think about my solution?

try “in_array”

there is full documentation at php.net

Maybe I have not understood your problem exactly, and re-using your test case (thanks, I like that, very thoughtful).


$a = array(1, 2, 3, 4); 
$b = array(2, 3, 4); 

    //$minus = minus_set($a, $b); 
    //print_r($minus); 
    //result is Array ( [0] => 1 ) 

$c = array_diff($a, $b);

var_dump($c);

// 0 => 1

Thank for your opinion!

My idea is like Pullo’s idea but I don’t use array_push function so it may be longer than him. Thank!

I have a feeling my version might be reducable, but meh…

(Note: I changed the input variable to $in)

$keys = array_unique(array_merge_recursive($in))[0]; //Find all keys
$values = array_combine($keys,array_pad(array(),count($keys),0)); //Fill with 0's. Creating a 'row' for the matrix.
$replace = array_map(function($item) { return array_combine($item,array_pad(array(),count($item),1)); }, $in); //All my 1's.
$out = array_pad(array(),count($in),$values); //Matrix of 0's.
$out = array_replace_recursive($out,$replace); //Put the 1's in the matrix.

PHP belches array-to-string issues at me on my Replace line, but i’m not… entirely sure where i’m converting a string in there… anyway, it works.

Nice one StarLion. That’s really neat!
I hadn’t heard of array_replace_recursive or array_merge_recursive, so I’ve just been reading the docs for those.
Now my head is ready to explode :slight_smile: