0

It's weird how simple things like these I cannot find about php on the internet. Without further ado, how do I find an element inside an array that already has a string index, with a position?

For example:

$array = ["apple"=>"red","raspberry"=>"blue","green","yellow"] // As you can see this is a mixed array
for($i=0;$i<=count($array);$i++){
   var_dump(getelementfrompos($array,$i)) // pseudocode
}
// output

array(2) => {
   [key] => string(5) "apple";
   [value] => string(3) "red"
}

array(2) => {
   [key] => string(9) "raspberry";
   [value] => string(4) "blue"
}

array(2) => {
   [key] => integer(2);
   [value] => string(5) "green"
}

array(2) => {
   [key] => integer(3);
   [value] => string(6) "yellow"
}

DUMBED DOWN VERSION:

$array = ["apple"=>"red"]
getkeyfrompos($array,0) // returns -> "apple"

How do I find an element inside an array that already has a string index, with a position, as if it was an element with a numerical index instead?

3 Answers3

0

Use array_keys() to get all the keys of the array, then index into that.

function getkeyfrompos($array, $index) {
    return array_keys($array)[$index];
}

function getelementfrompos($array, $index) {
    return $array[getkeyfrompos($array, $index)];
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

I'm not entirely sure why you would want to do what you're asking, you could use array_values and then do an array_search on the value but this would not work well for duplicate values.

Perhaps, this is where you could just create a wrapper. Rather than access properties of your array with [0] you could access the object property with ->{0}.

For example, a wrapper like this:

class IndxedArrayWrapper
{
    private object $properties;
    
    public function __construct(array $properties)
    {
        $this->properties = (object) [];
        
        array_walk($properties, fn($key, $value) => $this->__set($key, $value));
    }
    
    public function __get(string|int $index): mixed
    {
        return $this->properties?->{$index} ?? null;
    }
    
    public function __set(string|int $key, mixed $value): void
    {
        $this->properties->{count((array) $this->properties)} = ['key' => $key, 'value' => $value];
    }
}

Could be used like this:

$myArrayWrapper = (new IndxedArrayWrapper([
    'apple' => 'red',
    'bananna' => 'yellow'
]));

// apple, red
['key' => $fruit, 'value' => $colour] = $myArrayWrapper->{0};

// bannna, yellow
['key' => $fruit, 'value' => $colour] = $myArrayWrapper->{1};

You can see an example working over on 3v4l.org but this seems extremely overkill. Forgive me if I've mistaken what your intent is but I hope this helps.


Further reading:

Jaquarh
  • 6,493
  • 7
  • 34
  • 86
0

Use array_keys(). Your expectations were not completely clear so, in my solution I assume that if the original array element did not have a key, I will return NULL.

class Temp
{
    protected $initialArray;
    protected $keys;

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->ingest(["apple"=>"red","raspberry"=>"blue","green","yellow"]); // As you can see this is a mixed array
        

        for ( $i=0; $i < $this->count(); $i++ ) {
            var_dump($this->getelementfrompos($i)); // pseudocode
        }
        return 0;
    }

    protected function count() : int
    {
        return count($this->array);
    }
    /**
     * returns key of array element.
     * returns null if the original array element had no key.
     */
    protected function getelementfrompos(int $x) {
        if ( $x < 0 || $x >= $this->count() ) {
            throw new \Exception("index {$x} out of bounds");
        }
        // Adjust to suit
        if ( ! is_string($this->keys[$x]) || is_numeric($this->keys[$x]) ) {
            return null;
        }
        return $this->keys[$x];
    }

    protected function ingest(array $array)
    {
        $this->initialArray = $array;
        $this->keys = array_keys($this->initialArray);
    }
}

Output

string(5) "apple"
string(9) "raspberry"
NULL
NULL
ryantxr
  • 4,119
  • 1
  • 11
  • 25