-2

I've been searching for this and can't find it, though it's hard to put in to words so I apologize if it's covered elsewhere.

I have an API call I make that gives me this. This is shifts worked on a given date and there is an array for each shift. This is what one looks like.

$lastMon = array{
       date => $date
       hours => 8
       worker => mjones
       etc
       }

Now I want to take the recruiter value and the hours value and create another array that looks like this

$lastMonData = array{
       key for each $lastMon->recruiter => sum of all $lastMon->hours where recruiter is unique
       total += $lastMon->hours
       }

Basically, I have a bunch of shifts I extract from this system and turn it in to arrays and insert some keys I pull from other parts of the system. I then need an array by date that contains the total hours worked for all the shifts that day, and then a key for each unique name in the recruiter key that adds up the hours mentioned in the same array. I hope this makes sense.

EDIT:

Here is an example

SimpleXMLElement Object
(
    [orderId] => 4000262
    [status] => filled
    [shiftStartTime] => 2018-12-10T07:30:00
    [shiftEndTime] => 2018-12-10T12:30:00
    [tempId] => 80231
    [firstName] => SimpleXMLElement Object
        (
        )

    [lastName] => SimpleXMLElement Object
        (
        )

    [clientId] => 42642
    [clientName] => SimpleXMLElement Object
        (
        )

    [regionName] => SimpleXMLElement Object
        (
        )

    [orderSpecialty] => School
    [orderCertification] => RN
    [floor] => SimpleXMLElement Object
        (
        )

    [shiftNumber] => 1
    [note] => SimpleXMLElement Object
        (
        )

    [payrollNumber] => SimpleXMLElement Object
        (
        )

    [lessLunchMin] => SimpleXMLElement Object
        (
        )

    [dateTimeCreated] => 2018-08-17T09:33:43
    [takenBy] => 592
    [bookedByUserId] => 592
    [orderTypeId] => 1
    [orderType] => SimpleXMLElement Object
        (
        )

    [city] => Holmdel
    [state] => NJ
    [zipCode] => 07733
    [orderSourceID] => SimpleXMLElement Object
        (
        )

    [orderSourceName] => SimpleXMLElement Object
        (
        )

    [lt_orderID] => 13643
    [dateTimeModified] => 2018-08-17T09:33:43
    [recruiter] => John Smith
    [hours] => 05
)
SimpleXMLElement Object
(
    [orderId] => 4002473
    [status] => filled
    [shiftStartTime] => 2018-12-10T09:00:00
    [shiftEndTime] => 2018-12-10T13:30:00
    [tempId] => 1397353
    [firstName] => SimpleXMLElement Object
        (
        )

    [lastName] => SimpleXMLElement Object
        (
        )

    [clientId] => 47597
    [clientName] => SimpleXMLElement Object
        (
        )

    [regionName] => SimpleXMLElement Object
        (
        )

    [orderSpecialty] => School
    [orderCertification] => RN
    [floor] => SimpleXMLElement Object
        (
        )

    [shiftNumber] => 1
    [note] => SimpleXMLElement Object
        (
        )

    [payrollNumber] => SimpleXMLElement Object
        (
        )

    [lessLunchMin] => SimpleXMLElement Object
        (
        )

    [dateTimeCreated] => 2018-08-20T08:53:23
    [takenBy] => 592
    [bookedByUserId] => 592
    [orderTypeId] => 1
    [orderType] => SimpleXMLElement Object
        (
        )

    [city] => Tinton Falls
    [state] => NJ
    [zipCode] => 07701
    [orderSourceID] => SimpleXMLElement Object
        (
        )

    [orderSourceName] => SimpleXMLElement Object
        (
        )

    [lt_orderID] => 0
    [dateTimeModified] => 2018-08-20T10:05:33
    [recruiter] => Mike Jones
    [hours] => 04
)

I need to take the recruiter value and make those in to keys in a new array. Some repeat, so I would only want to take the unique ones. Then, the hours value in this array would be the value for the recruiter name key in the new array.

So this would then look like

$lastMon = array{
      Mike Jones => 4
      John Smith => 5
      Total => 9
}
mobirae
  • 1
  • 4
  • What have you tried so far and what is your specific problem? What's wrong with looping trough your first array and creating the second one during that? – Jeff Dec 19 '18 at 00:34
  • 1
    I think I understand what you're asking, but I need to see a real example of your input data to explain how you can do it. In general you will get much better results asking questions here if the examples you provide are either real parseable PHP code or at least var_dump/print_r output. – Don't Panic Dec 19 '18 at 00:47
  • Can you post your expected output. Also, there is no 'recruiter' value. What would it be? – Ice76 Dec 19 '18 at 00:53
  • I will post what I'm looking at. I changed recruiter to worker too. Sorry about that. But what I have is values from another arrays keys. I need the unique values there, which are names, to then be keys in a new array with their values being a sum of the hours key from the original array for each name. Then I also sum all the hours together across all names. But I will post the entire original array in a minute. – mobirae Dec 19 '18 at 14:43

1 Answers1

0

You can use array-reduce to aggregate the recruiter hours:

$lastMon = array(array("recruiter" => "AAA", "hours" => 4), array("recruiter" => "BBB", "hours" => 5), array("recruiter" => "AAA", "hours" => 3));

function reduceHours($carry, $item)
{
    if (!array_key_exists($item["recruiter"], $carry))
        $carry[$item["recruiter"]] = 0;
    $carry[$item["recruiter"]] += $item["hours"];
    return $carry;
}


$lastMonData = array_reduce($lastMon, "reduceHours", array());

This will output:

Array
(
    [AAA] => 7
    [BBB] => 5
)

Edited

Now that you added more data I can give you more detailed answer:

$str = '<xml><shifts><recruiter>John Smith</recruiter><hours>05</hours></shifts><shifts><recruiter>Mike Jones</recruiter><hours>04</hours></shifts><shifts><recruiter>John Smith</recruiter><hours>08</hours></shifts></xml>';
$arr = json_decode(json_encode((array) simplexml_load_string($str)), 1);

function sum($carry, $item) { return $carry + $item;}
function reduceHours($carry, $item)
{
    if (!array_key_exists($item["recruiter"], $carry))
        $carry[$item["recruiter"]] = 0;
    $carry[$item["recruiter"]] += $item["hours"];
    return $carry;
}

$lastMonData = array_reduce($arr["shifts"], "reduceHours", array());
$lastMonData["total"] = array_reduce($lastMonData, "sum");

Converting xml object to array is from here.

This will give output for $lastMonData:

Array
(
    [John Smith] => 13
    [Mike Jones] => 4
    [total] => 17
)

I know the sum of total can be done in other ways but I tried to keep the example of using array_reduce.

dWinder
  • 11,597
  • 3
  • 24
  • 39
  • This is pretty much exactly what I'm looking for. I just can't get it to work. Sorry yesterday was a long day, but $lastMon is from a simplexml_load_string so it's an object not an array. How could I change that to account for it? But that's what I want it to do is combine the recruiter key values so there isn't any duplicates, and then combine the hours values where the recruiter repeats. – mobirae Dec 19 '18 at 17:33
  • You rock man `Array ( [Gloria M] => 13 [Shana A] => 3 [Cynthia W] => 14 [Tony C] => 4 [Alexandra C] => 5 [Sarah D] => 12 [Lindsey S] => 4 [Casi D] => 7 [Salina T] => 4 [Madeline S] => 4 [Max M] => 7 [Jeanine S] => 16 [Michael B] => 2 [Gretchen D] => 3 [total] => 98 )` – mobirae Dec 19 '18 at 22:25
  • So, this doesn't 100% work actually. Since it's a date time it doesn't add up properly. I'm trying to find the answer, but I figured I would ask you. I end up just a bit off because with += it's trying to treat the "hours" as strings but it's a datetime. I don't know how to adjust the function to use the "add" date interval function? – mobirae Jan 15 '19 at 19:24
  • In your question the `hours` where strings and we add them as integer (PHP will understand they are number). What do you mean by datatime? I didn't use the `shiftStartTime` key. If you want to calculate the hours dynamically you can use [this](https://stackoverflow.com/questions/676824/how-to-calculate-the-difference-between-two-dates-using-php) – dWinder Jan 15 '19 at 20:21
  • You're absolutely right, it's an int. So, what's happening is it's being added incorrectly. All of the times are either top of the hour or 15 minutes intervals. However, I'm ending up with really weird times. I put %i in the format to see the minutes and this is what I get. Would it be from serializing and unserializing it? Name";d:165.5;s:15:"Name";d:199.20000000000002;s:11:"Name";d:203.15000000000003;s:13:"Name";d:93.6;s:13:"Name";d:16.6;s:0:"";i:0;s:16:"Name";d:141.64999999999998 – mobirae Jan 15 '19 at 20:25
  • Can you please open new question about it? I still don't fully understand your problem and using those comment is not the way to do it... – dWinder Jan 15 '19 at 20:34
  • https://stackoverflow.com/questions/54206552/reducing-arrays-adding-ints-incorrectly – mobirae Jan 15 '19 at 20:45