patternphpMinor
Filtering by value X from array Y with a fallback
Viewed 0 times
arraywithvaluefallbackfromfiltering
Problem
I wrote a function that solve a special problem. But one of my 'special hardcore software engineers' told me that this is a bad solution - but he will not give me a better solution. So I ask you: What could I do better? (This is more an academic exercise than a bottleneck in my software.)
I have an array
First value (index 0) of
If this function finds a higher priority tag type during its iteration thru
Expected result 1:
Expected result 2:
This is my function - I hope comments will clarify everything.
```
/**
* This function filters and returns one or many tags of a defined tag type.
* Define tag types in $types - first tag type (index 0) has highest priority.
* This function returns only highest
* tag type found and will ignore lower priority tag types.
*
* @param Tag[] $tags Array of tag models
* @param int[] $types Array of tag types, first (index 0) has highest priority
* @param int $count Max tags of one type to be returned
* @return Tag[]
*/
public function filterTagsByType($tags, $types, $count = 1)
{
$priority = 1000;
$returnTags = [];
foreach ($tags as $tag)
{
// get priority level of this tag,
I have an array
$tags of {n} objects. Each object has an attribute called type. Further I have an array $types of {n} integers (tag types). First value (index 0) of
$types has highest priority, second value (index 1) of $types second highest priority and so on.If this function finds a higher priority tag type during its iteration thru
$tags it discards the lower priority tags from $returnArray.$count just tell this function how many tags of same tag type are allowed. So if there are three tags of highest priority tag type it will return first occurrence.Expected result 1:
$tags = [
$obj1, //type 50
$obj2, //type 1
$obj3 //type 25
]
$types = [1, 50]
filterTagsByType($tags, $types) //returns [$obj2] because it has type 1Expected result 2:
$tags = [
$obj1, //type 50
$obj3 //type 25
]
$types = [1, 50]
filterTagsByType($tags, $types) //returns [$obj1] because it has type 50This is my function - I hope comments will clarify everything.
```
/**
* This function filters and returns one or many tags of a defined tag type.
* Define tag types in $types - first tag type (index 0) has highest priority.
* This function returns only highest
* tag type found and will ignore lower priority tag types.
*
* @param Tag[] $tags Array of tag models
* @param int[] $types Array of tag types, first (index 0) has highest priority
* @param int $count Max tags of one type to be returned
* @return Tag[]
*/
public function filterTagsByType($tags, $types, $count = 1)
{
$priority = 1000;
$returnTags = [];
foreach ($tags as $tag)
{
// get priority level of this tag,
Solution
Edit:
You code is over complex knowing there are some really good built in php functions to filter an array.
I think that is where the 'special hardcore dev' started disliking your code. Here an example that uses an anonymous function and array_filter. It also does the same as in the other answer. Loop over the $types instead of the tags. I think it is safe to say that there will be more tags then types.
You should ofcourse still add the count check. this is easy with array_slice:
Not sure how this is performance wise, but it shouldn't be an issue.
You code is over complex knowing there are some really good built in php functions to filter an array.
I think that is where the 'special hardcore dev' started disliking your code. Here an example that uses an anonymous function and array_filter. It also does the same as in the other answer. Loop over the $types instead of the tags. I think it is safe to say that there will be more tags then types.
function filterTagsByType($tags, $types, $count = 1)
{
$tagFilter = function($type) {
return function($tag) use($type) {
return $tag->type == $type;
};
};
foreach ($types as $type) {
$filteredTags = array_filter($tags, $tagFilter($type));
if ( count($filteredTags) > 0 ) {
return $filteredTags;
}
}
return array();
}You should ofcourse still add the count check. this is easy with array_slice:
return array_slice($filteredTags, 0, $count);Not sure how this is performance wise, but it shouldn't be an issue.
Code Snippets
function filterTagsByType($tags, $types, $count = 1)
{
$tagFilter = function($type) {
return function($tag) use($type) {
return $tag->type == $type;
};
};
foreach ($types as $type) {
$filteredTags = array_filter($tags, $tagFilter($type));
if ( count($filteredTags) > 0 ) {
return $filteredTags;
}
}
return array();
}return array_slice($filteredTags, 0, $count);Context
StackExchange Code Review Q#61449, answer score: 4
Revisions (0)
No revisions yet.