Musterknabe
Musterknabe

Reputation: 6081

Use Generators as multidimensional array replacement

some time ago I built a tool, and got told by some guys to use Generators instead of simple arrays to have better performance etc. I started using Generators, however, googling issues for Generators is pretty useless, since there isn't much information yet for Generators. So, let's come to my question

Let's imagine the following code

$array  = [0, 1, 2, 3, 4, 5];
$mapper = ['zero', 'one', 'two', 'three', 'four', 'five'];

function mapNumbers($array, $mapper)
{
    foreach ($array as $element) {
        yield $element => $mapper[$element];
    }
}

foreach (mapNumbers($array, $mapper) as $key=>$value) {
    print $key . ' | ' . $value . '<br>';
}

This gives the following output

0 | zero
1 | one
2 | two
3 | three
4 | four
5 | five

However, what I now want to do, is an array that is multidimensional. Let's imagine the following

$categories = ['food', 'nonfood'];
$products   = ['food' => ['meat', 'fish'], 'nonfood' => ['table', 'stool']];

function mapCategories($categories, $products)
{
    foreach ($categories as $category) {
        yield 'Category' => $category, 'Products' => $products[$category]
    }
}

foreach (mapCategories($categories, $products) as $key=>$value) {
    // do something
}

This doesn't work of course, because this line is giving out errors

yield 'Category' => $category, 'Products' => $products[$category]

Is what I'm trying to do even possible with Generators? When learning Generators for the first time I thought Generators are there to replace arrays in some circumstances, but it doesn't seem like they replace arrays when trying to build multidimensional arrays.

Is this possible? If yes, how? If no, how would I combine this with Generators? Or is it either only generators or only arrays?

Many thanks

Upvotes: 1

Views: 1859

Answers (2)

Mark Baker
Mark Baker

Reputation: 212452

While you can use a Generator to achieve what you want:

$categories = ['food', 'nonfood'];
$products   = ['food' => ['meat', 'fish'], 'nonfood' => ['table', 'stool']];

function mapCategories($categories, $products) {
    foreach ($categories as $category) {
        yield ['Category' => $category, 'Products' => $products[ $category]];
    }
}

foreach (mapCategories($categories, $products) as $key=>$value) {
    echo $key, ' => '; var_dump($value); echo PHP_EOL;
}

There are no real benefits to doing so, other than readability of the code. The real benefit of Generators is when you're actively retrieving/generating the data dynamically, when you gain the memory benefits of only holding the data that you need when it's actually needed, and when it may be faster to do so. Simply remapping data that you've already loaded into PHP memory doesn't give any speed or memory benefits.

In your case, simply remapping the data using array_map() can provide the merged structure that you want, while still maintaining a good degree of readability:

$categories = ['food', 'nonfood'];
$products   = ['food' => ['meat', 'fish'], 'nonfood' => ['table', 'stool']];

foreach (
    array_map(
        function ($value) use ($products) {
            return ['Category' => $value, 'Products' => $products[$value]];
        },
        $categories
    ) as $value) {
        var_dump($value);
}

Upvotes: 2

Bahadır Birs&#246;z
Bahadır Birs&#246;z

Reputation: 181

I think what you want is as follows :

$categories = ['food', 'nonfood'];
$products   = ['food' => ['meat', 'fish'], 'nonfood' => ['table', 'stool']];

function mapCategories($categories, $products)
{
    foreach ($categories as $category) {
        foreach ($products as $product) {
            yield $category => $product;
        }
    }
}

# OR 

function mapCategories($categories, $products)
{
    foreach ($categories as $category) {
        yield $category => $products[$category];
    }
}

Upvotes: 0

Related Questions