2

I have a large array.

In this array I have got (among many other things) a list of products:

$data['product_name_0'] = '';
$data['product_desc_0'] = '';
$data['product_name_1'] = '';
$data['product_desc_1'] = '';

This array is provided by a third party (so I have no control over this).

It is not known how many products there will be in the array.

What would be a clean way to loop though all the products?

I don't want to use a foreach loop since it will also go through all the other items in the (large) array.

I cannot use a for loop cause I don't know (yet) how many products the array contains.

I can do a while loop:

$i = 0;
while(true) { // doing this feels wrong, although it WILL end at some time (if there are no other products)
    if (!array_key_exists('product_name_'.$i, $data)) {
        break;
    }

    // do stuff with the current product

    $i++;
}

Is there a cleaner way of doing the above?

Doing a while(true) looks stupid to me or is there nothing wrong with this approach.

Or perhaps there is another approach?

PeeHaa
  • 71,436
  • 58
  • 190
  • 262

3 Answers3

4

Your method works, as long as the numeric portions are guaranteed to be sequential. If there's gaps, it'll miss anything that comes after the first gap.

You could use something like:

$names = preg_grep('/^product_name_\d+$/', array_keys($data));

which'll return all of the 'name' keys from your array. You'd extract the digit portion from the key name, and then can use that to refer to the 'desc' section as well.

foreach($names as $name_field) {
   $id = substr($names, 12);
   $name_val = $data["product_name_{$id}"];
   $desc_val = $data["product_desc_{$id}"];
}
Marc B
  • 356,200
  • 43
  • 426
  • 500
  • This solution is the cleanest imo, not sure why one would opt for a while loop control when foreach does the job. – Mike Purcell Nov 04 '11 at 17:32
  • 1
    Nice. I like this. Question though. Speed-wise, how does `preg_grep` perform? Is it essentially looping through the whole set to run the regex, then looping on the matches again? Still, if you're aren't guaranteed to have sequential items, this is a winner. – Eric G Nov 04 '11 at 17:40
  • It'll parse the array once and return any matches. Then the foreach only loops on those matches. So if you've got 50 $data entries, you'll get 25 'name' matches, and the foreach will iterate 25 times. Speedwise, it's probably slower than doing a simple substr comparison to see if the array keys start with `product_name_`, but the preg version would allow for checking much more complicate key patterns. – Marc B Nov 04 '11 at 17:42
1

How about this

$i = 0;
while(array_key_exists('product_name_'.$i, $data)) {
    // loop body
    $i++;
}
Michael Mior
  • 28,107
  • 9
  • 89
  • 113
1

I think you're close. Just put the test in the while condition.

$i = 0;
while(array_key_exists('product_name_'.$i, $data)) { 
    // do stuff with the current product

    $i++;
}

You might also consider:

$i = 0;
while(isset($data['product_name_'.$i])) { 
    // do stuff with the current product

    $i++;
}

isset is slightly faster than array_key_exists but does behave a little different, so may or may not work for you:

What's quicker and better to determine if an array key exists in PHP?

Difference between isset and array_key_exists

Community
  • 1
  • 1
Eric G
  • 3,427
  • 5
  • 28
  • 52
  • 1
    the fact that `isset()` behaves differently than `array_key_exists()` it the reaseon I didn't use it :) Thanks though – PeeHaa Nov 04 '11 at 17:33