0

Not quite sure how to word this correctly, but I am looking for some help to to move/shift array keys so that the top level array doesn't contain another array with only one item. Basically from this:

[0] => Array
    (
        [0] => Array
            (
                [_id] => 3
                [title] => Award winning wedding venue
                [subtitle] => Creating a website to reflect the prestige of the brand
            )

    )

[1] => Array
    (
        [0] => Array
            (
                [_id] => 5
                [title] => Bringing storytelling to life
                [subtitle] => Bringing storytelling to life
            )

    )

to be like this:

[0] => Array
    (
        [_id] => 3
        [title] => Award winning wedding venue
        [subtitle] => Creating a website to reflect the prestige of the brand
    )

[1] => Array
    (
        [_id] => 5
        [title] => Bringing storytelling to life
        [subtitle] => Bringing storytelling to life
    )

Almost just shifting the array key up one.

The original array is created using the following:

// Start with manual relation otherwise default to next/prev    
    foreach ($item['related'] as $id) {
      
      $related[] = perch_collection('Projects', [
        'filter' => [
          [
            'filter' => '_id',
            'match'  => 'eq',
            'value'  => $id,
          ],
            // Item is enabled
          [
            'filter' => 'status',
            'match' => 'eq',
            'value' => 'enabled',
          ],
        ],
        'skip-template' => true,
      ], true);
    }
5
  • 2
    Do you have any control over how the array is created in the first place. This is usually the most efficient way of sorting this sort of problem out. Commented Jun 26, 2020 at 13:08
  • I do partly, I will edit the question to show the code example. Commented Jun 26, 2020 at 13:12
  • 1
    Try changing the last part of the method call to ], true)[0]; with the extra [0] to say take the first element of the result. Commented Jun 26, 2020 at 13:17
  • Thanks @NigelRen, this also worked. Although I didn't expect it to. Commented Jun 26, 2020 at 13:34
  • Not going to close this one with stackoverflow.com/q/6193946/2943403 because Grumpy has given more suitable advice for this particular case. Commented Jun 26, 2020 at 15:42

2 Answers 2

1

It would be best if you modify the creation of your array instead of changing it afterwards.

// Start with manual relation otherwise default to next/prev    
foreach ($item['related'] as $id) {
  
    $related[] = perch_collection('Projects', [
        'filter' => [
            [
                'filter' => '_id',
                'match'  => 'eq',
                'value'  => $id,
            ],
            // Item is enabled
            [
                'filter' => 'status',
                'match' => 'eq',
                'value' => 'enabled',
            ],
        ],
        'skip-template' => true,
  ], true)[0];
}

Note the [0] at the end of the perch_collection() function call. This is essentially the same as the second part of my answer, it just occurs earlier.


With that said, if you still want to change it after the original array is made, you could just use a simple foreach loop with a reference to the original array.

foreach($array as &$arr) {
    $arr = $arr[0];
}

Using & in front of $arr is a reference. This means the loop will alter the original array, so it prevents the overhead of a temporary array.


mickmackusa let me know about another solution using array_column(), which avoids the loop completely.

$array = array_column($array, 0);
Sign up to request clarification or add additional context in comments.

5 Comments

array_column() can be used to mop up too. stackoverflow.com/a/45417345/2943403, but I agree that it is best to not create the mess in the first place.
@mickmackusa That's a cool solution, I use array_column() a lot but never thought about the possibility of using it with a numbered index.
I don't mean to offend, but I eventually found a duplicate that provides all of the necessary guidance and hammered the question.
@mickmackusa Nah that's just the way the site works! No offense taken. Thanks for finding a suitable dupe.
I looked at the earlier post that it was closed with and felt that it departed from the guidance that I wanted to extend to this question. It was deliberate. No, it is the non-standard thing to do. Ideally, all of the Stack Overflow duplicates should "collapse" down to the best&earliest questions.
1

The best way to fix this problem would be at the source. This looks like a Dataset received from a database, so instead of trying to manipulate the array after you received it, you could also try to generate it in the correct format. Most DALs have methods to manipulate the return type of the resultset.

However, if that is not possible and you always only have a single element nested, this loop should do the trick.

for($i = 0; $i <= count($array); $i++) {
    $shifted[$i] = $array[$i][0];
}

2 Comments

isn't count() called on every single loop, making this method very expensive? Of course, to solve that, you could just declare the count of $array before the loop. It probably also doesn't really matter too much unless you are doing thousands of rows.
@GrumpyCrouton it is, I just wrote that thing real quick during lunch break. Also, count is very performant and even thousands of rows probably won't result in a noticeable performance degredation. But in general it's cleaner to declare the count before the loop.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.