Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quickest way to restructure an array?

I have an array which can have several items in it, e.g:

Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
etc

I need the quickest way to restructure this array so that it has at most X items. So if I say that X is 3, the resulting array must be:

Item 1 , Item 2
Item 3, Item 4
Item 5, Item 6
etc

or if it has 7 items, it would be:

Item 1 , Item 2, Item 3,
Item 4, Item 5, 
Item 6, Item 7

What's the easiest way to do this?

I started with this, but it seems like there really must be an easier way:

foreach ($addressParts as $part)
{
    if (empty($part)) continue;
    if (empty($addressLines[$count]))  $addressLines[$count] = '';
    $addressLines[$count] .= $part;
    $count++;
    if ($count > 2) $count = 0;
}

Also, this won't work, because you will end up with this:

item 1, item 4, item 7
item 2, item 5
item 3, item 6

... which is wrong. Any thoughts?

UPDATE

If I start with:

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

I want to end with:

Array
(
    [0] => item 1, item 2, item 3
    [1] => item 4, item 5
    [2] => item 6, item 7
)

Make sense?

like image 776
coderama Avatar asked Oct 30 '13 13:10

coderama


People also ask

Can we increase size of array after declaration?

Arrays can either hold primitive values or object values. An ArrayList can only hold object values. You must decide the size of the array when it is constructed. You can't change the size of the array after it's constructed.

How do you restructure an array?

Arrays can be restructured in four ways: Splitting a one-dimensional array into multiple one-dimension arrays. Folding a one-dimensional array into a multidimensional array. Flattening a multidimensional array into a one-dimensional array.

Can an array be modified?

No problem—you can modify the values in arrays as easily as other variables. One way is to access an element in an array simply by referring to it by index.


2 Answers

This function combines elements to a new array as per your example. It handles any number of input elements.

function ReduceArray($input, $length) {
        $frac = $length / count($input);
        $frac = $frac + 0.0001;    // Offset for float calculations
        $index = 0.0;

        // Copy the elements, rolling over on $index
        $temp = array();
        foreach ($input as $part) {
                $i= floor($index);
                if (!isset($temp[$i])) {
                        $temp[$i] = array($part);
                } else {
                        $temp[$i][] = $part;
                }
                $index += $frac;
        }

        // Combine the sub arrays
        $output = array();
        foreach ($temp as $line) {
            $output[] = implode(', ', $line);
        }
        return $output;
}

$input = array('Item 1',  'Item 2',  'Item 3',  'Item 4',  'Item 5',  'Item 6', 'Item 7');
$output = ReduceArray($input, 3);
print_r($output);

Output

Array
(
    [0] => Item 1, Item 2, Item 3
    [1] => Item 4, Item 5
    [2] => Item 6, Item 7
)

Edit "fixed" the output as per the given output.

Edit See Comment for nine elements, tested for up to 12 elements. Thanks sectus

like image 104
Stephan B Avatar answered Oct 14 '22 01:10

Stephan B


For each group, calculate to offset of the first element and the group length, copy that slice from the input array.

function array_group_elements($array, $groups) {
  $result = array();
  $count = count($array);
  // minimum in each group
  $limit = floor($count / $groups);
  // balance, modulo
  $overhead = $count % $groups;
  // for each group
  for ($i = 0; $i < $groups; ++$i) {
    // group offset, add 1 for each group that got a balance element
    $offset = ($i * $limit) + ($i < $overhead ? $i : $overhead);
    // length, add 1 if it is a group with balance element
    $length = $limit + ($i < $overhead ? 1 : 0);
    // copy slice from original array
    $result[] = array_slice($array, $offset, $length);
  }
  return $result;
}

$input = array('Item 1',  'Item 2',  'Item 3',  'Item 4',  'Item 5',  'Item 6', 'Item 7');
$grouped = array_group_elements($input, 3);
var_dump(
  array_map(
    function($group) {
      return implode(', ', $group);
    },
    $grouped
  )
);

Output:

array(3) {
  [0]=>
  string(22) "Item 1, Item 2, Item 3"
  [1]=>
  string(14) "Item 4, Item 5"
  [2]=>
  string(14) "Item 6, Item 7"
}

The function array_group_elements() loops over the $groups (3 times), not the $array (7 times).

like image 39
ThW Avatar answered Oct 14 '22 00:10

ThW