0

Hi i am running the following code.

foreach ($response as $object) {

$basename = basename($object);

$structure = explode("/", $object);

echo $structure[0] . '<br>';


}

this returns the following.

MINOFSOUDUB412
MINOFSOUDUB412
MINOFSOUDUB412
MotionTracker.zip
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker
MotionTracker

i only want it to return one unique name like below

MINOFSOUDUB412
MotionTracker.zip
MotionTracker

Can someone help me with this

Thanks

3 Answers 3

4

array_unique would be the right choice. Just pass the exploded array to this function and you will get what you need.

You could look it in here: http://php.net/manual/en/function.array-unique.php

Sign up to request clarification or add additional context in comments.

Comments

2
foreach ($response as $object) {
    $basename = basename($object);
    $structure = explode("/", $object); 
    echo $structure[0] . '<br>';
    ...
}

If you want to prevent duplicates in echo'ing out $structure[0], you need to check whether you have had it already, e.g. by keeping a history:

$history = array();
foreach ($response as $object) {
    $name = strstr($object, "/", true);
    if ($name !== false && !isset($history[$name])) {
        $history[$name] = 1;
        echo $name . '<br>';
    }
    ...
}

You probably want to stream line your code. Let's review:

foreach ($response as $object) {

    $basename = basename($object);

    $structure = explode("/", $object);

    echo $structure[0] . '<br>';


}

The line $basename = basename($object); is not used. It can be removed:

foreach ($response as $object) {

    $structure = explode("/", $object);

    echo $structure[0] . '<br>';

}

Then you only need the part of the string until the first "/", the strstr function is handy for that:

foreach ($response as $object) {

    $part = strstr($object, "/", true);
    FALSE === $part && $part = $object;

    echo $part . '<br>';

}

Now as we have already simplified it that much, we can create a simple mapping function:

$map = function($v) {
    $k = strstr($v, "/", true);
    FALSE === $k && $k = $v;
    return $k;
};

and map the $response:

$mapped = array_map($map, $response);

and then unique it:

$unique = array_unique($mapped);

And job done. The code is much more easy to read:

$map = function($v) {
    $k = strstr($v, "/", true);
    FALSE === $k && $k = $v;
    return $k;
};

$mapped = array_map($map, $response);

$unique = array_unique($mapped);

foreach ($unique as $name) {
    echo $name, "<br>\n";
}

The additional benefit is here, in the moment you care about the output, the data to be outputted is already in order and properly available. As output itself counts as one part of your application, it should not be mixed with the data processing. See the IPO Model.

4 Comments

+1 Doing it in one loop, and proper checking... Should really be the accepted answer.
@Corbin: that depends, there can be a use in first streamlining the data or doing it all in one iteration. Because arrays are used, it's normally okay to spit the operation across mulitple steps, e.g. using array_map, array_unique etc. - however if an iteration is used, then it's better to implement it inside each iteration. Normally I'd say array functions do best work, I'll add an example as well.
Really here he accomplishes both goals of building an array of unique values and outputting them in one iteration. There's not really a downside to this approach. As for array functions, I wouldn't use them in this situation, though I suppose they would read more cleanly.
Yes, it's not really judgeable what makes more sense with the information given, but I edited the answer anyway ;)
1

You will get the best performance out of using the value as an array key:

$unique = array();
while (...) {
    $unique[$name] = true;
}
print_r(array_keys($unique);

This seems a bit crazy at first. After all, why use the string as an array key?

Well: $unique[$name] is O(1) (meaning no matter how large the array is it takes the same amount of time) whereas in_array($name, $unique) is O(n) meaning it grows with how many entries are in the array.

Just for reference the full version of it in your code would be:

$unique = array();

foreach ($response as $object) {
    $basename = basename($object);
    $structure = explode("/", $object);
    $unique[$structure[0]] = true;
    //You could also do: $unique[$structure[0]] = $structure[0];
    //Then your second foreach could be:
    //foreach ($unique as $name)
}

foreach ($unique as $name => $fake) { echo $name . '<br>'; }

The O(n) (slower version) would be:

$unique = array();
foreach ($response as $object) {
    $basename = basename($object);
    $structure = explode("/", $object);
    if (!in_array($structure[0], $unique)) {
        $unique[] = $structure[0];
    }
}

The slower version is slower, but people not intimately familiar with PHP arrays may find it a bit easier to read.

9 Comments

@DCHP and what I suggested, doesn't?
@Eugene Yours will work, but requires building the entire array and then basically doing a hash map behind the scenes. In other words, it's a sort of hybrid of the two approaches offered. It will take up the most space and likely be the slowest, however, it probably would end up cleaner looking code.
@Corbin well depends on what author is looking for. Less code or more performance.
@Eugene It would be two lines fewer at best :)
@Corbin I would still go with less.
|

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.