Search for an item in inner array - php

I have an assoc array looking like this (the data comes from user input, this is just an example)
$startingDate = "2020-10-20";
$daysBetween[] = "2020-10-21", "2020-10-22", "2020-10-23";
$endingDate = "2020-10-24";
$eventDates[ID] => [
"startingDate" => $startingDate,
"daysBetween" => $daysBetween,
"endingDate" => $endingDate,
];
How would I look for a specific startingDate for example if I don't want to loop over every ID. Basically I'm looking for a way to do something like $eventDates[*]["startingDate"]

You can achieve this a few different ways, one being array_filter().
$searchFor = '2020-09-20';
$result = array_filter($eventDates, function($v) use ($searchFor) {
return ($v['startingDate'] ?? null) == $searchFor;
});
This returns the array(s) where you match the $searchFor variable with a column startingDate. If you just want the first one, use $result = array_shift($result); to get the first one.
This approach basically filters out any results where the callback doesn't return true. By including use ($searchFor) the variable becomes visible inside the scope of that function, otherwise it would be undefined within that scope.
Live demo at https://3v4l.org/iaT8k

The questioner states that they are looking for a way to do something like
$eventDates[*]["startingDate"]
The PHP equivalent to this is:
foreach ($eventDates as $id => $eventDate) {
//look at $eventDate["startingDate"] and if it matches the criteria do whatever required
//you know the ID (=$id) so you can save/return/use that if needed.
}

Related

Conditional unset from Guzzle response

I've seen a few questions and the ones worth referencing
How can i delete object from json file with PHP based on ID
How do you remove an array element in a foreach loop?
How to delete object from array inside foreach loop?
Unset not working in multiple foreach statements (PHP)
The last two from the list are closer to what I'm intending to do.
I've got a variable names $rooms which is storing data that comes from a particular API using Guzzle
$rooms = Http::post(...);
If I do
$rooms = json_decode($rooms);
this is what I get
If I do
$rooms = json_decode($rooms, true);
this is what I get
Now sometimes the group exists in the same level as objectId, visibleOn, ... and it can assume different values
So, what I intend to do is delete from $rooms when
group isn't set (so that specific value, for example, would have to be deleted)
group doesn't have the value bananas.
Inspired in the last two questions from the initial list
foreach($rooms as $k1 => $room_list) {
foreach($room_list as $k2 => $room){
if(isset($room['group'])){
if($room['group'] != "bananas"){
unset($rooms[$k1][$k2]);
}
} else {
unset($rooms[$k1][$k2]);
}
}
}
Note that $room['group'] needs to be changed to $room->group depending on if we're passing true in the json_decode() or not.
This is the ouput I get if I dd($rooms); after that previous block of code
Instead, I'd like to have the same result that I've shown previously in $rooms = json_decode($rooms);, except that instead of having the 100 records it'd give only the ones that match the two desired conditions.
If I am not totally wrong, then this should do the trick for you:
$rooms = json_decode($rooms);
$rooms->results = array_values(array_filter($rooms->results, function($room) {
return property_exists($room, 'group') && $room->group != "banana";
}));
Here is a verbose and commented version of this one above:
$rooms = json_decode($rooms);
// first lets filter our set of data
$filteredRooms = array_filter($rooms->results, function($room) {
// add your criteria for a valid room entry
return
property_exists($room, 'group') // the property group exists
&& $room->group == "banana"; // and its 'banana'
});
// If you want to keep the index of the entry just remove the next line
$filteredRooms = array_values($filteredRooms);
// overwrite the original results with the filtered set
$rooms->results = $filteredRooms;

Find out if string matches array key, return value for that key

I am working on an import script that needs to evaluate whether the set string fits with the possible values the backend field can have.
More exactly what I have is this array of committes:
$committees = array(
'Ämter' => 1,
'Abteilungen' => 2,
'Konservatoren' => 3,
'Dienstagssitzung' => 4,
);
and now I need to figure out if a string saved in
variable $category matches any key in that array. If it does match one of the entries, I need it to return the value (1, 2, 3 or 4) that goes with that key.
I read up about it here on Stackoverflow and found plenty examples to see if a value equals one in an array, for example:
preg_match array items in string?
and tried to follow those along.
I tried
$committeesKeys = '/(' . implode('|', array_keys($committees)) . ')/';
$matches = preg_match($committeesKeys, $category);
but that only returned how many matches it found?
I also tried
$input = preg_quote($category, '/');
$matches = preg_filter('/'.$input.'/', null, $committees);
as that was suggested somehwere else, can't find the link anymore, but that returned an empty array.
I am new to all of this so might be totally wrong here.
Can anybody tell me how I can do this, or where I can find an answer to the question? I might just not have found it, my brain is rather tired right now...
I feel that I have right to post that as answer accepted :-) :
echo (isset($committees[$category]))?$committees[$category]:'There is no '.$category.' category';
you can do something like this:
function getValue($category){
if (array_key_exists($category, $committees)){
return $committees[$category]; //the value you want
}
}
Hope this helps :)
preg_match() has a 3rd argument which will allow you to save capture groups into a numerical array. However, if you want to compare a string directly you can simply use a loop and strcmp or === which will probably work faster since preg_match has to compile the regex you define in the first argument. My solution for this problem would look like:
$found = FALSE;
foreach ( $committees as $name=>$number ) {
if ( $name === $category ) {
$found = $number;
}
}
return $found;
You make it difficult by not showing what is in the category matches.
Maybe something like this.
$results = array_intersect ($matches,$committees );

Remove an item from an associative array php

How can I remove from this array the current selected language:
$lang = 'en-US';
$languages = array('LANG001' => 'en-US', 'LANG002' => 'es-ES', 'LANG003' => 'fr-CA');
I try with unset($languages[$lang]) without success.
Thanks.
try:
unset($languages[array_search($lang,$languages,true)]);
1) The index in an array expression must be the key, not the value. If you want to delete an element by the value, you have to find its key first.
$key = array_search($lang, $languages);
if ($key) {
unset($languages[$key]);
}
However, this will only remove the first occurrence of the value in the array. If the value can appear multiple times and you want to remove all of them, you can do:
$languages = array_diff($languages, array($lang));
Why do you want to echo specific values in a loop?
You'd use a loop to echo values depending on a pattern or simply every value.
To access variables inside of a loop, you'd do it the same way as everywhere else in a script,
check if the variable exists then echo that specific var.
Simply use
(isset($languages['LANG001']) ? echo $languages['LANG001'] : null);
(isset($languages['LANG002']) ? echo $languages['LANG002'] : null);

Find index of value in associative array in php?

If you have any array $p that you populated in a loop like so:
$p[] = array( "id"=>$id, "Name"=>$name);
What's the fastest way to search for John in the Name key, and if found, return the $p index? Is there a way other than looping through $p?
I have up to 5000 names to find in $p, and $p can also potentially contain 5000 rows. Currently I loop through $p looking for each name, and if found, parse it (and add it to another array), splice the row out of $p, and break 1, ready to start searching for the next of the 5000 names.
I was wondering if there if a faster way to get the index rather than looping through $p eg an isset type way?
Thanks for taking a look guys.
Okay so as I see this problem, you have unique ids, but the names may not be unique.
You could initialize the array as:
array($id=>$name);
And your searches can be like:
array_search($name,$arr);
This will work very well as native method of finding a needle in a haystack will have a better implementation than your own implementation.
e.g.
$id = 2;
$name= 'Sunny';
$arr = array($id=>$name);
echo array_search($name,$arr);
Echoes 2
The major advantage in this method would be code readability.
If you know that you are going to need to perform many of these types of search within the same request then you can create an index array from them. This will loop through the array once per index you need to create.
$piName = array();
foreach ($p as $k=>$v)
{
$piName[$v['Name']] = $k;
}
If you only need to perform one or two searches per page then consider moving the array into an external database, and creating the index there.
$index = 0;
$search_for = 'John';
$result = array_reduce($p, function($r, $v) use (&$index, $search_for) {
if($v['Name'] == $search_for) {
$r[] = $index;
}
++$index;
return $r;
});
$result will contain all the indices of elements in $p where the element with key Name had the value John. (This of course only works for an array that is indexed numerically beginning with 0 and has no “holes” in the index.)
Edit: Possibly even easier to just use array_filter, but that will not return the indices only, but all array element where Name equals John – but indices will be preserved:
$result2 = array_filter($p, function($elem) {
return $elem["Name"] == "John" ? true : false;
});
var_dump($result2);
What suits your needs better, resp. which one is maybe faster, is for you to figure out.

PHP Date merging class / method?

I am doing work where I get data in various formats from various sources. I will end up with something like this:
$dataSource1 = ... ;
$dataSource2 = ... ;
$dataSource3 = ... ;
I need to COMBINE these data sources, all with different field names, into one object, that I can sort according to fields, limit to X number etc.... all for display purposes.
What is the best way to do this? Is there a good php library that does this?
Three possible solutions,
You could always create a database and just use that. (Probably the best thing to do)
Alternatively, you could try attempt to do some polymorphisisng? (cant be made into a verb!)
Finally, you could also include all the other pages into the one you will be displaying from.
(I suggest number 1)
I think the simplest way is using an associative array.
$dataSource1 = ...;
$dataSource2 = ...;
...
$dataSourceN = ...;
$data = array()
$data[0] = $dataSource1;
$data[1] = $dataSource2;
And so on. Just remember that a numeric index array always starts at 0. So the first element would be $data[0].
If you want a more complex bind you can create a multidimensional array. It means you can sort by specific fields. See an example:
$data1 = 'Brazil';
$dataArray = array()
$dataArray[] = array(
'countryId' => 'id',
'countryName' => $data1,
'usersFromThisCountry' => $data1Users
);
Now you can sort $dataArray according to 'countryId','countryName','usersFromThisCountry'.

Categories