Page 1 of 1

merging a single array

Posted: Fri Dec 07, 2007 12:30 pm
by s.dot
Say you have this array:

Code: Select all

Array
(
    [0] => Array
    (
        [1] => value
        [2] => value
        [3] => value
    )

    [1] => Array
    (
        [1] => value
        [2] => value
        [3] => value
    )

    [2] => Array
    (
        [1] => value
        [2] => value
        [3] => value
    )
)
What's the best way to merge this into a single array, so the above array would look like:

Code: Select all

Array
(
    [0] => value
    [1] => value
    [2] => value
    [3] => value
    [4] => value
    [5] => value
    [6] => value
    [7] => value
    [8] => value
)

Posted: Fri Dec 07, 2007 12:46 pm
by feyd
Depending on how you want the logic to work, it may be a simple array_filter(), array_values(), array_diff() -type mashing.

Posted: Fri Dec 07, 2007 12:51 pm
by s.dot
Would that be any better or more efficient than..

Code: Select all

$values = array();
foreach ($arr AS $subArr)
{
    foreach ($subArr AS $value)
    {
        $values[] = $sub;
    }
}

Posted: Fri Dec 07, 2007 1:58 pm
by nathanr
Not sure if it would be more efficient, however this would let you be a bit more recursive..

Code: Select all

<?php
class array_handler {
	protected $values;
	
	public function getValues($array) {
		$this->values = array();
		$this->returnValues($array);
		return $this->values;
	}
	
	protected function returnValues($tree) {
		foreach ($tree as $key=>$value) {
			if(is_array($value)) {
				$this->returnValues($value);
			} else {
				$this->values[] = $value;
			}
		}
	}
}
?>
obviously this raises the issue of associative arrays, value ordering and the fact there's probably a far easier method..

a random thought.. surely to get that array you had to build it, in which case why didn't you build it flat?

yet another way

Posted: Sat Dec 08, 2007 8:26 am
by yacahuma
feyd | Please use

Code: Select all

,

Code: Select all

and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read:  [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]

Code: Select all

$arr = array(array('val1','val2','val3'),
             array('val4','val5','val6'),
             array('val7','val8','val9'));

$narr = array();
foreach ($arr as $v)  $narr = array_merge ($narr,$v);
I have no clue how fast will be one compared to the other. Of course this will not give you the flexibility if you have more array levels.


feyd | Please use

Code: Select all

,

Code: Select all

and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read:  [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]

Posted: Sat Dec 08, 2007 9:26 am
by feyd

Code: Select all

<?php

	$test = array(
		array(
			array(
				'val1',
				'val2',
				'val3',
			),
			'val4',
			'val5',
		),
		array(
			'val6',
			array(
				'val7',
				'val8',
				'val9',
			),
			'val10',
		),
		array(
			'val11',
			'val12',
			array(
				'val13',
				'val14',
				'val15',
			),
		),
	);
	
	$expected = array(
		'val1',
		'val2',
		'val3',
		'val4',
		'val5',
		'val6',
		'val7',
		'val8',
		'val9',
		'val10',
		'val11',
		'val12',
		'val13',
		'val14',
		'val15',
	);
				
	function array_flatten_recursive(array $d)
	{
		$out = array();
		foreach($d as $v)
		{
			if (is_array($v))
			{
				$out = array_merge($out, array_flatten_recursive($v));
			}
			else
			{
				$out[] = $v;
			}
		}
		
		return $out;
	}

	function array_flatten(array $d)
	{
		$s   = array(array(array_values($d),0));
		$out = array();
		
		$c = 0;
		
		do
		{
			$z = count($s);
			$j = $z - 1;
			for($i = $s[$j][1], $l = count($s[$j][0]);
				$i < $l;
				++$i)
			{
				if (is_array($s[$j][0][$i]))
				{
					$s[$j][1] = $i + 1;
					$s[] = array(array_values($s[$j][0][$i]), 0);
					break;
				}
				else
				{
					$out[] = $s[$j][0][$i];
				}
			}
			
			if ($i >= $l)
			{
				array_pop($s);
			}
			else
			{
				continue;
			}
		}
		while(count($s) > 0);
		
		return $out;
	}
	
	$result = array_flatten_recursive($test);
	
	echo 'array_flatten_recursive() ' . 
		($result == $expected ? 'PASSED' : 'FAILED' . PHP_EOL . 
			var_export($result, true)) . 
		PHP_EOL . PHP_EOL;

	$result = array_flatten($test);
	
	echo 'array_flatten() ' . 
		($result == $expected ? 'PASSED' : 'FAILED' . PHP_EOL . 
			 var_export($result, true)) . 
		PHP_EOL . PHP_EOL;

Code: Select all

feyd:~ feyd$ php -f arraycrush.php
array_flatten_recursive() PASSED

array_flatten() PASSED

Posted: Mon Dec 10, 2007 1:08 pm
by Kieran Huggins
Complete with unit testing and everything!

Dude.... nice.

Posted: Mon Dec 10, 2007 6:59 pm
by feyd
Kieran Huggins wrote:Complete with unit testing and everything!

Dude.... nice.
It was easier to add quick'n'dirty unit tests rather than trying to compare by eye with that many values. ;)