Get Element at N position in an Array without Loop - php

How get you get element key and value of an at the n position array at a particular position without loop.
Imagine
$postion = 3; // get array at 3rd position
$array = array(
"A" => "Four",
"B" => "twp",
"C" => "three",
"D" => "Four",
"E" => "Five",
"F" => "Four");
$keys = array_keys($array);
$value = array_values($array);
echo implode(array_slice($keys, $postion, 1)), PHP_EOL; // Key at 3rd posstion
echo implode(array_slice($value, $postion, 1)), PHP_EOL; // Value at n position
Output
D
Four
Issues With the method is
Multiple Duplication of the array resulting higher memory usage
Why not use loop
You have to get multiple position multiple times .. looping large data set not efficient either
Why not use a Database
Yes working with memory based database like Redis can make life easier but am particular array optimisation
Why not use SplFixedArray
This would have been solution but i the follow weer because am not using positive keys ( I really this is nor fair on php part)
Fatal error: Uncaught exception 'InvalidArgumentException'
with message 'array must contain only positive integer keys'
What do you mean by large data set :
Actually i stumble on this issue when trying to as this question Managing mega Arrays in PHP so am looking at 1e6 or 1e7 with 512M memory limit
Am sure something like fseek for array would do the trick .. but not sure if that exists

Assuming PHP 5.4, with array dereferencing:
echo $array[array_keys($array)[$position]];
In earlier versions you need to break it into two lines:
$keys = array_keys($array);
echo $array[$keys[$position]];
It would also be worth using the two-line approach in 5.4+ if you have to access multiple elements, to allow you to only call the relatively expensive array_keys() function once. Also the dereferencing approach assumes that the specific position within the array exists, which it may not. Breaking it into multiple operations would allow you to handle that error case.
Although of course you don't ever need access to the key, you can simply do:
echo array_values($array)[$position];
// or
$values = array_values($array);
echo $values[$position];
Edit
The ArrayIterator class can also do this for you:
$iterator = new ArrayIterator($array);
$iterator->seek($position);
echo $iterator->key(), " = ", $iterator->current(); // D = Four
This is probably the least expensive way to do this assuming it doesn't create a copy of the array in memory when you do it (still researching this element), and likely the best method for multiple accesses of arbitrary keys.

What you want is not possible. PHP's arrays have efficient access by key, but don't have efficient access by offset. The order is only available as a linked list, so the best efficiency you can hope for is an O(n) loop, which just goes through the array and looks for the offset:
$i = 0;
foreach ($array as $value) {
if ($i++ === $offset) {
// found value
}
}
If you want this operation to be fast, then you'll have to use a proper, numerically and sequentially indexed array.

in fact you don't need the $values array:
$keys = array_keys($array);
$value_3=$array[$keys[3]];

I dont understand your question well but if you need a key and element from position
$position = 3; // get array at 3rd position
$array = array(
"A" => "Four",
"B" => "twp",
"C" => "three",
"D" => "Four",
"E" => "Five",
"F" => "Four");
$keys = array_keys($array);
$values = array_values($array);
if($values[$position] == "Four" && $keys[$position] == "D") {
echo "All it's Right!\n";
}
you dont need implode for that task

Related

PHP: How to extract this string

Suppose I've got the following string:
) [6] => Array ( [2014-05-05 00:0] => My actual content
If I want to only be left with My actual content at the end, what is the best way to split the entire string?
Note: the words My actual content are and can change. I'm hoping to cut the string based on the second => string as this will be present at all times.
It seems you're just looking to find the first value of an array with keys you do not know. This is super simple:
Consider the following array:
$array = array(
'2014-05-22 13:36:00' => 'foo',
'raboof' => 'eh',
'qwerty' => 'value',
'8838277277272' => 'test'
);
Method #1:
Will reset the array pointer to the first element and return it.
Using reset:
var_dump( reset($array) ); //string(3) "foo"
DEMO
Method #2:
Will reset the entire array to use keys of 0, 1, 2, 3...etc. Useful if you need to get more than one value.
Using array_values:
$array = array_values($array);
var_dump( $array[0] ); //string(3) "foo"
DEMO
Method #2.5:
Will reset the entire array to use keys of 0, 1, 2, 3...etc and select the first one into the $content variable. Useful if you need to get more than one value into variables straight away.
Using list and array_values:
list( $content ) = array_values($array);
var_dump( $content ); //string(3) "foo"
DEMO
Method #3:
Arrays are iteratable, so you could iterate through it but break out immediately after the first value.
Using a foreach loop but break immediatly:
foreach ($array as $value) {
$content = $value;
break;
}
var_dump($content); //string(3) "foo"
DEMO
To Answer your question, on extracting from a string based on last 'needle'...
Okay, this is quite an arbitrary question, since it seems like you're showing us the results from a print_r(), and you could reference the array key to get the result.
However, you mentioned "... at the end", so I'm assuming My actual content is actually right at the end of your "String".
In which case there's a very simple solution. You could use: strrchr from the PHP manual - http://www.php.net/manual/en/function.strrchr.php.
So you're looking at this: strrchr($string, '=>');
Hope this answers your question. Advise otherwise if not please.
you have to use foreach loop in a foreach to get the multi dimentional array values.
foreach($value as $key){
foreach($key as $val){
echo $val;
}
}

Start foreach loop on associative array at the second element

I have associative array such as:
$myArray = array(
'key1' => 'val 1',
'key2' => 'val 2'
...
);
I do not know the key values up front but want to start looping from the second element. In the example above, that would be from key2 onwards.
I tried
foreach(next(myArray) as $el) {
}
but that didnt work.
Alternatives may be array_slice but that seems messy. Am i missing something obvious?
There really is no "one true way" of doing this. So I'll take it as a benchmark as to where you should go.
All information is based on this array.
$array = array(
1 => 'First',
2 => 'Second',
3 => 'Third',
4 => 'Fourth',
5 => 'Fifth'
);
The array_slice() option. You said you thought this option was overkill, but it seems to me to be the shortest on code.
foreach (array_slice($array, 1) as $key => $val)
{
echo $key . ' ' . $val . PHP_EOL;
}
Doing this 1000 times takes 0.015888 seconds.
There is the array functions that handle the pointer, such as ...
current() - Return the current element in an array.
end() - Set the internal pointer of an array to its last element.
prev() - Rewind the internal array pointer.
reset() - Set the internal pointer of an array to its first element.
each() - Return the current key and value pair from an array and advance the array cursor.
Please note that the each() function has been deprecated as of PHP 7.2, and will be removed in PHP 8.
These functions give you the fastest solution possible, over 1000 iterations.
reset($array);
while (next($array) !== FALSE)
{
echo key($array) . ' ' . current($array) . PHP_EOL;
}
Doing this 1000 times, takes 0.014807 seconds.
Set a variable option.
$first = FALSE;
foreach ($array as $key => $val)
{
if ($first != TRUE)
{
$first = TRUE;
continue;
}
echo $key . ' ' . $val . PHP_EOL;
}
Doing this 1000 times takes 0.01635 seconds.
I rejected the array_shift options because it edits your array and you've never said that was acceptable.
This depends on whether you want to do this just once or many times, and on whether you still need the original array later on.
"First" pattern
$first = true;
foreach ($array as $key=>value) {
if($first) {
$first = false;
continue;
}
// ... more code ...
}
I personally use this solution quite often because it's really straight-forward, everybody gets this. Also, there is no performance hit of creating a new array and you can still operate on the original array after the loop.
However, if you have a couple of loops like this, it kind of starts looking a little unclean, because you need 5 extra lines of code per loop.
array_shift
array_shift($array);
foreach ($array as $key=>value) {
// .... more code ....
}
array_shift is a function tailored to this special case of not wanting the first element. Essentially it's a Perl-ish way of saying $array = array_slice($array, 1) which might not be completely obvious, especially since it modifies the original array.
So, you might want to make a copy of the original array and shift it, if you need both the shifted array multiple times and also the original array later on.
array_slice
And, of course, there is array_slice itself. I don't see anything wrong with array_slice if you want the original array to remain unchanged and you need the sliced array multiple times. However, if you're positive that you always want to slice just one element off, you might as well use the shorthand array_shift (and make a copy before if needed).
You can go with the obvious way:
$flag = false;
foreach($myArray as $el) {
if($flag) {
// do what you want
}
$flag = true;
}
Just another way of flexible iteration:
reset($myArray); // set array pointer to the first element
next($myArray); // skip first element
while (key($myArray) !== null) {
// do something with current($myArray)
next($myArray);
}
As far as I know foreach is just a kind of shortcut for this construction.
From Zend PHP 5 Certication study guide:
As you can see, using this set of functions [reset, next, key,
current, ...] requires quite a bit of work; to be fair, there are some
situations where they offer the only reasonable way of iterating
through an array, particularly if you need to skip back-and-forth
between its elements. If, however, all you need to do is iterate
through the entire array from start to finish, PHP provides a handy
shortcut in the form of the foreach() construct.
If your array was 0 based, it would be if($key>=1), but as your array starts at key 1, then this should work.
foreach ($array as $key=>$value){if($key>=2){
do stuff
}}
You could try:
$temp = array_shift($arr);
foreach($arr as $val) {
// do something
}
array_unshift($arr, $temp);
reset($myArray);
next($myArray);
while ($element = each($myArray))
{
//$element['key'] and $element['value'] can be used
}
My fairly simple solution when this issue pops up. It has the nice advantage of being easily being modified to be able to skip more than just the first element if you want it to.
$doomcounter = 0;
foreach ($doomsdayDevice as $timer){ if($doomcounter == 0){$doomcounter++; continue;}
// fun code goes here
}

How do I remove a specific key in an array using php?

I have an array with 4 values. I would like to remove the value at the 2nd position and then have the rest of the key's shift down one.
$b = array(123,456,789,123);
Before Removing the Key at the 2nd position:
Array ( [0] => 123 [1] => 456 [2] => 789 [3] => 123 )
After I would like the remaining keys to shift down one to fill in the space of the missing key
Array ( [0] => 123 [1] => 789 [2] => 123 )
I tried using unset() on the specific key, but it would not shift down the remaining keys. How do I remove a specific key in an array using php?
You need array_values($b) in order to re-key the array so the keys are sequential and numeric (starting at 0).
The following should do the trick:
$b = array(123,456,789,123);
unset($b[1]);
$b = array_values($b);
echo "<pre>"; print_r($b);
It is represented that your input data is an indexed array (there are no gaps in the sequence of the integer keys which start from zero). I'll compare the obvious techniques that directly deliver the desired result from the OP's sample data.
1. unset() then array_values()
unset($b[1]);
$b = array_value($b);
This is safe to use without checking for the existence of the index -- if missing, there will be no error.
unset() can receive multiple parameters, so if more elements need to be removed, then the number of function calls remains the same. e.g. unset($b[1], $b[3], $b[5]);
unset() cannot be nested inside of array_values() to form a one-liner because unset() modifies the variable and returns no value.
AFAIK, unset() is not particularly handy for removing elements using a dynamic whitelist/blacklist of keys.
2. array_splice()
array_splice($b, 1, 1);
// (input array, starting position, number of elements to remove)
This function is key-ignorant, it will target elements based on their position in the array. This is safe to use without checking for the existence of the position -- if missing, there will be no error.
array_splice() can remove a single element or, at best, remove multiple consecutive elements. If you need to remove non-consecutive elements you would need to make additional function calls.
array_splice() does not require an array_values() call because "Numerical keys in input are not preserved" -- this may or may not be desirable in certain situations.
3. array_filter() nested in array_values()
array_values(
array_filter(
$b,
function($k) {
return $k != 1;
},
ARRAY_FILTER_USE_KEY
)
)
This technique relies on a custom function call and a flag to tell the filter to iterate only the keys.
It will be a relatively poor performer because it will iterate all of the elements regardless of the logical necessity.
It is the most verbose of the options that I will discuss.
It further loses efficiency if you want to employ an in_array() call with a whitelist/blacklist of keys in the custom function.
Prior to PHP7.4, passing a whitelist/blacklist/variable into the custom function scope will require the use of use().
It can be written as a one-liner.
This is safe to use without checking for the existence of the index(es) -- if missing, there will be no error.
4. array_diff_key() nested in array_values()
array_values(
array_diff_key(
$b,
[1 => '']
)
);
This technique isn't terribly verbose, but it is a bit of an overkill if you only need to remove one element.
array_diff_key() really shines when there is a whitelist/blacklist array of keys (which may have a varying element count). PHP is very swift at processing keys, so this function is very efficient at the task that it was designed to do.
The values in the array which is declared as the second parameter of array_diff_key() are completely irrelevant -- they can be null or 999 or 'eleventeen' -- only the keys are respected.
array_diff_key() does not have any scoping challenges, compared to array_filter(), because there is no custom function called.
It can be written as a one-liner.
This is safe to use without checking for the existence of the index(es) -- if missing, there will be no error.
Use array_splice().
array_splice( $b, 1, 1 );
// $b == Array ( [0] => 123 [1] => 789 [2] => 123 )
No one has mentioned this, so i will do: sort() is your friend.
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach($fruits as $key => $val)
echo "fruits[$key] = $val";
output:
fruits[0] = apple
fruits[1] = banana
fruits[2] = lemon
fruits[3] = orange
// remove Lemon, too bitter
unset($fruits[2]);
// keep keys with asort
asort($fruits);
foreach($fruits as $key => $val)
echo "fruits[$key] = $val";
Output:
fruits[0] = apple
fruits[1] = banana
fruits[3] = orange
This is the one you want to use to reindex the keys:
// reindex keys with sort
sort($fruits);
foreach($fruits as $key => $val)
echo "fruits[$key] = $val";
Output:
fruits[0] = apple
fruits[1] = banana
fruits[2] = orange
If you want to remove an item from an array at a specific position, you can obtain the key for that position and then unset it:
$b = array(123,456,789,123);
$p = 2;
$a = array_keys($b);
if ($p < 0 || $p >= count($a))
{
throw new RuntimeException(sprintf('Position %d does not exists.', $p));
}
$k = $a[$p-1];
unset($b[$k]);
This works with any PHP array, regardless where the indexing starts or if strings are used for keys.
If you want to renumber the remaining array just use array_values:
$b = array_values($b);
Which will give you a zero-based, numerically indexed array.
If the original array is a zero-based, numerically indexed array as well (as in your question), you can skip the part about obtaining the key:
$b = array(123,456,789,123);
$p = 2;
if ($p < 0 || $p >= count($b))
{
throw new RuntimeException(sprintf('Position %d does not exists.', $p));
}
unset($b[$p-1]);
$b = array_values($b);
Or directly use array_splice which deals with offsets instead of keys and re-indexes the array (numeric keys in input are not preserved):
$b = array(123,456,789,123);
$p = 2;
if ($p < 0 || $p >= count($b))
{
throw new RuntimeException(sprintf('Position %d does not exists.', $p));
}
array_splice($b, $p-1, 1);

How do I move an array element with a known key to the end of an array in PHP?

Having a brain freeze over a fairly trivial problem. If I start with an array like this:
$my_array = array(
'monkey' => array(...),
'giraffe' => array(...),
'lion' => array(...)
);
...and new elements might get added with different keys but always an array value. Now I can be sure the first element is always going to have the key 'monkey' but I can't be sure of any of the other keys.
When I've finished filling the array I want to move the known element 'monkey' to the end of the array without disturbing the order of the other elements. What is the most efficient way to do this?
Every way I can think of seems a bit clunky and I feel like I'm missing something obvious.
The only way I can think to do this is to remove it then add it:
$v = $my_array['monkey'];
unset($my_array['monkey']);
$my_array['monkey'] = $v;
array_shift is probably less efficient than unsetting the index, but it works:
$my_array = array('monkey' => 1, 'giraffe' => 2, 'lion' => 3);
$my_array['monkey'] = array_shift($my_array);
print_r($my_array);
Another alternative is with a callback and uksort:
uksort($my_array, create_function('$x,$y','return ($y === "monkey") ? -1 : 1;'));
You will want to use a proper lambda if you are using PHP5.3+ or just define the function as a global function regularly.
I really like #Gordon's answer for its elegance as a one liner, but it only works if the targeted key exists in the first element of the array. Here's another one-liner that will work for a key in any position:
$arr = ['monkey' => 1, 'giraffe' => 2, 'lion' => 3];
$arr += array_splice($arr, array_search('giraffe', array_keys($arr)), 1);
Demo
Beware, this fails with numeric keys because of the way that the array union operator (+=) works with numeric keys (Demo).
Also, this snippet assumes that the targeted key is guaranteed to exist in the array. If the targeted key does not exist, then the result will incorrectly move the first element to the end because array_search() will return false which will be coalesced to 0 by array_splice() (Demo).
You can implement some basic calculus and get a universal function for moving array element from one position to the other.
For PHP it looks like this:
function magicFunction ($targetArray, $indexFrom, $indexTo) {
$targetElement = $targetArray[$indexFrom];
$magicIncrement = ($indexTo - $indexFrom) / abs ($indexTo - $indexFrom);
for ($Element = $indexFrom; $Element != $indexTo; $Element += $magicIncrement){
$targetArray[$Element] = $targetArray[$Element + $magicIncrement];
}
$targetArray[$indexTo] = $targetElement;
}
Check out "moving array elements" at "gloommatter" for detailed explanation.
http://www.gloommatter.com/DDesign/programming/moving-any-array-elements-universal-function.html

Which is proper form?

PHP.
$a['0']=1;
$a[0]=2;
Which is proper form?
In the first example you use a string to index the array which will be a hashtable "under the hood" which is slower. To access the value a "number" is computed from the string to locate the value you stored. This calculation takes time.
The second example is an array based on numbers which is faster. Arrays that use numbers will index the array according to that number. 0 is index 0; 1 is index 1. That is a very efficient way of accessing an array. No complex calculations are needed. The index is just an offset from the start of the array to access the value.
If you only use numbers, then you should use numbers, not strings. It's not a question of form, it's a question of how PHP will optimize your code. Numbers are faster.
However the speed differences are negligible when dealing with small sizes (arrays storing less than <10,000 elements; Thanks Paolo ;)
In the first you would have an array item:
Key: 0
Index: 0
In the second example, you have only an index set.
Index: 0
$arr = array();
$arr['Hello'] = 'World';
$arr['YoYo'] = 'Whazzap';
$arr[2] = 'No key'; // Index 2
The "funny" thing is, you will get exactly the same result.
PHP (for whatever reason) tests whether a string used as array index contains only digits. If it does the string is converted to int or double.
<?php
$x=array(); $x['0'] = 'foo';
var_dump($x);
$x=array(); $x[0] = 'foo';
var_dump($x);
For both arrays you get [0] => foo, not ["0"] => foo.
Or another test:<?php
$x = array();
$x[0] = 'a';
$x['1'] = 'b';
$x['01'] = 'c';
$x['foo'] = 'd';
foreach( $x as $k=>$v ) {
echo $k, ' ', gettype($k), "\n";
}0 integer
1 integer
01 string
foo string
If you still don't believe it take a look at #define HANDLE_NUMERIC(key, length, func) in zend_hash.h and when and where it is used.
You think that's weird? Pick a number and get in line...
If you plan to increment your keys use the second option. The first one is an associative array which contains the string "0" as the key.
They are both "proper" but have the different side effects as noted by others.
One other thing I'd point out, if you are just pushing items on to an array, you might prefer this syntax:
$a = array();
$a[] = 1;
$a[] = 2;
// now $a[0] is 1 and $a[1] is 2.
they are both good, they will both work.
the difference is that on the first, you set the value 1 to a key called '0'
on the second example, you set the value 2 on the first element in the array.
do not mix them up accidentally ;)

Categories