1

I have an array

$var = [
    "one" => "one",
    "two" => "two",
    "three" => "three",
    "four" => "four"
];

If I passed keys one and three, I want to get values one, two, and three with their keys.

Now I am doing is

$new_array = array_diff(array_slice($var,$key1),array_slice($var,$key2));
$new_array[$key1] = $var[$key1];
$new_array[$key2] = $var[$key2];
9
  • what do you mean if you passed keys 0,2 you want to get one , two ,three? Based on what? Commented Jul 6, 2012 at 8:07
  • 2
    I don't know if i get your question right, but doesn't array_slice(array,index_begin, index_end) provide the desired behaviour? Commented Jul 6, 2012 at 8:07
  • @Adnan . Based on keys , 0 and 2 are keys Commented Jul 6, 2012 at 8:08
  • still doesn't explain why passing 0 and 2 would return one, two and three Commented Jul 6, 2012 at 8:09
  • 2
    @Adnan He wants to get the values where the keys are in the range 0 -> 2, so 0 = one, 1 = two, 2 = three Commented Jul 6, 2012 at 8:10

3 Answers 3

4

You pass in a key $from and a key $to. To have something from - to working, you need to know the order as well. You get the order of keys with array_keys:

$keys = array_flip(array_keys($array));

Now you can locate both the offset of $from and $to keys:

array_slice($array, $keys[$from], $keys[$to] - $keys[$from] + 1);

Compile as a full example:

<?php
/**
 * Most efficient way to get keys,values between two keys of an Associative array
 * @link http://stackoverflow.com/q/11358192/367456
 */

$array = array("one" => "one", "two" => "two", "three" => "three", "four" => "four");

$slice = function($from, $to) use ($array)
{
    $keys = array_flip(array_keys($array));
    if (isset($keys[$from]) and isset($keys[$to])) {
        return array_slice($array, $keys[$from], $keys[$to] - $keys[$from] + 1);
    }
    throw new InvalidArgumentException('Invalid from and/or to key.');
};

var_dump($slice('one', 'three'));

Output:

array(3) {
  ["one"]=>
  string(3) "one"
  ["two"]=>
  string(3) "two"
  ["three"]=>
  string(5) "three"
}
Sign up to request clarification or add additional context in comments.

Comments

3

Assuming your input array has contiguous keys, why not just:

$newArray = array_slice($array, $key1, $key2 + 1);

EDIT

Oh wait, that will only work when $key1 = 0, try this instead:

$newArray = array_slice($array, $key1, ($key2 - $key1) + 1);

This still requires that $key1 < $key2, but from what you say I imagine it always will be.

ANOTHER EDIT

In order to accomplish this without looping the array (with would of course be the easiest way) you need to convert the string keys to numerics so they can be used with array_slice(). This works:

$var = array("one"=>"one","two"=>"two","three"=>"three","four"=>"four");
$key1 = 'one';
$key2 = 'three';

$keys = array_keys($var);
$key1index = array_search($key1, $keys);
$key2index = array_search($key2, $keys);

$newArray = array_slice($var, $key1index, ($key2index - $key1index) + 1, TRUE);

print_r($newArray);

7 Comments

hmm, am working with an associative array . so simply can not do mathematical operations
@KanishkaPanamaldeniya Well that's easily solved - just change it to $newArray = array_slice(array_values($array), $key1, ($key2 - $key1) + 1);
@KanishkaPanamaldeniya If you're not working with the kind of array you post in your question, how should one help you? Post the data you're working with.
when you use array_slice and work with an associative array you can set preserve_key flag true
@KanishkaPanamaldeniya Do you wish to preserve the keys? Also, when working with an associative array you should work with the names of the keys and your code should be agnostic of the order the keys occur within the array. If you want to grab an arbitrary chunk of the array, it only really makes sense if the array is indexed and you are using it like a stack.
|
0

In terms of time complexity, you can process the whole array in a single pass with just one nested condition block and a conditional break.

Obviously the following algorithm can easily be adjusted to compare values or return an indexed array if desired.

The the starting point is matched or the result array is not empty, push the current value into the result array. If ending point matches the current value, then stop looping.

Code: (Demo)

$array = [
    "one" => "one",
    "two" => "two",
    "three" => "three",
    "four" => "four"
];

$start = 'one';
$end = 'three';
$result = [];
foreach ($array as $k => $v) {
    if ($start === $k || $result) {
        $result[$k] = $v;
        if ($end === $k) {
            break;
        }
    }
}
var_export($result);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.