1

I have a desc array created from a scandir(). Here is a small example of the array:

[7] => 20151227NY [8] => 20151226NY [9] => 20151221NY [10] => 20151125CT [11] => 20140313NY [12] => 20140228NY [13] => 20140227NY [14] => 20140226NH [15] => 20140226CT [16] => 20140128NJ [17] => 20140123NY [18] => 20140122CT [19] => 20140121NJ [20] => 20140102NY [21] => 20131231NJ 

These are all folders named using YearMonthDateState. I need a way to grab all the folders containing "NY", "CT", "NJ", "NH" and put them in separate arrays that sort in desc order(latest date first). That way I can get files I need in them according to the latest date(which is in the folder name). I tried this:

//GET WEEKLY FOLDER
$weekly_dir = "../email/weekly/";
$weekly_files = scandir($weekly_dir, $sorting_order = 1);
$weekly_index =  $weekly_files[7];
$weekly_state = substr($weekly_index, 8,2);
$new_weekly = str_replace($weekly_state, $template->State, $weekly_index);
echo $new_weekly;

But unfortunately, not every new "weekly" is uploaded on the same date. So I cant just switch the state string ("NY" "NH" etc) at the end. Any ideas?

**UPDATE:**I have added/modified the code as suggested by Michael so my code now looks like this:

$weekly_dir = "../email/weekly/";
$weekly_file_array = scandir($weekly_dir, $sorting_order = 1);
$index = $weekly_file_array;

// Prepare result
$weeklies = array_fill_keys(array_map(function ($item) {
if (substr($item, -2) == 'NY'){
    return substr($item, -2);
}
}, $index),$item);

// Split into state arrays
array_walk($index, function ($item) use (&$weeklies) {
    $state = substr($item, -2);
    $weeklies[$state][] = $item;
});

$weeklies_latest = array_combine(array_keys($weeklies), array_map(function ($item) {
    sort($item);
    return array_pop($item);
 }, $weeklies));

Seems to work just fine, but I get these two errors at the top of page: "Warning: sort() expects parameter 1 to be array, null given" "Warning: array_pop() expects parameter 1 to be array, null given". I am calling the $weeklies_latest array like this:

<a href="/COMM/email/weekly/<? echo $weeklies_latest[$template->State] ?>/weekly.html" class="button-link button-link-blue">CURRENT ISSUE</a>
2
  • can you provide an example: original filepath => actual array result => desired array result Commented Feb 10, 2016 at 16:10
  • The array result above is an actual excert from the dir array I have. I would like them to be their own arrays like so: $ny_weekly = array('20151227NY', '20151221NY', '20151214NY' etc...); $ct_weekly = array('20151220CT', '20151214CT', '20151208CT' etc...); etc... Commented Feb 10, 2016 at 16:25

1 Answer 1

1

I usually do it in two steps because it makes the code more readable.

First I prepare the result based on states, using a combination of array_fill_keys and array_map

// Prepare result
$weeklies = array_fill_keys(array_map(function ($item) {
    return substr($item, -2);
}, $input), []);

This builds an array with states as keys pointing to empty arrays. In the next step I once again "walk" through all the elements and then add them to the propper state array.

// Split into state arrays
array_walk($input, function ($item) use (&$weeklies) {
    $state = substr($item, -2);
    $weeklies[$state][] = $item;
});

(you see how this could just as well have been done in one step? you can use foreach instead of array_walk if you prefer that)

Now you are left with something like this:

Array
(
    [NY] => Array
        (
            [0] => 20151227NY
            [1] => 20151226NY
            [2] => 20151221NY
            [3] => 20140313NY
            [4] => 20140228NY
            [5] => 20140227NY
            [6] => 20140123NY
            [7] => 20140102NY
        )

    [CT] => Array
        (
            [0] => 20151125CT
            [1] => 20140226CT
            [2] => 20140122CT
        )

    [NH] => Array
        (
            [0] => 20140226NH
        )

    [NJ] => Array
        (
            [0] => 20140128NJ
            [1] => 20140121NJ
            [2] => 20131231NJ
        )

)

To pick the latest for each state you'll need to sort your dates since there is not guarantee of their order from the filesystem (it seems from your data). After sorting we pick the one at the end. I'm using array_pop since you might have a week where one day failed or whatnot, so it is better not to rely on perfect data:

$weeklies_latest = array_combine(array_keys($weeklies), array_map(function ($item) {
    sort($item);
    return array_pop($item);
 }, $weeklies));

I'm using array_combine because PHP doesn't have a built-in array_map that works on associative arrays.

$weekly_latest now contains this:

Array
(
    [NY] => 20151227NY
    [CT] => 20151125CT
    [NH] => 20140226NH
    [NJ] => 20140128NJ
)
Sign up to request clarification or add additional context in comments.

5 Comments

This works! Only one thing, I get 2 errors despite the fact that it seems to work: "Warning: sort() expects parameter 1 to be array, null given" and "Warning: array_pop() expects parameter 1 to be array, null given".
@Goten13 Yes you are using the 'fill' part wrong. Remove the if "NY" part. What is you goal? If it is to get only NY that is done in a different way.
@Goten13 I've edited your code here, I've left comments so you can see the changes. I've tested it like this and it works gist.github.com/mblarsen/01b1ee38264123f6da26
I noticed there are other files in the dir other than the folders I needed, so I was trying to filter those files out. That's what my if (substr($item, -2) == 'NY') condition was about. FILES IN DIR AFTER SORT: Array ( [hp] => weeklypreview.php [ck] => weeklypreview.bck [gn] => weekly-re-design [es] => images [og] => error_log [NY] => 20160211NY [NH] => 20160210NH [CT] => 20160210CT [NJ] => 20160209NJ [..] => .. [.] => . )
Then what you should do is make a check using array_filter before you send the data to the code I provided in my answer.

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.