Php array objects find

How to search through an array of objects?

I have an HTML template file that I parse with PHP and replace certain tags in the template with data stored in the objects. A template tag looks like:

These tags can also have more attributes:

The tags above contain a position and thus you can place your content of the same type in the top or the bottom of the template.

The data objects all use the same abstract class and have the same render function:

class PhpFragment extends FragmentBase < public function render() < //. render output for this type of data >> class CssFragment extends FragmentBase < public function render() < //. render output for this type of data >> class MetaFragment extends FragmentBase < public function render() < //. render output for this type of data >> 

This way I can use an universal function to render all the objects, unregarding the type of data it contains.

The Challenge

I need a way to quickly find certain objects inside the array. When I reach a certain tag inside the template, I need to render the data of the objects that match the type (and position if applicable) of this tag.

In my previous design I used an object with a lot of class properties that hold instances of FragmentBase , like:

Each class property contained an array of FragmentBase instances of a certain data-type to retrieve data from.

Читайте также:  Рандом случайных чисел python

But this design isn’t very easily maintained and is not very flexible. Also because the object that stored the data is universal, I needed to check the datatype to be able to render it with the correct function.

Is there a way to search through an array of objects fast or should I just stick to using the pageData object and store my fragment objects in that?

Yes, thats what I mean. With an associative array you can just use the array keys, you cant do that with an array of objects, so how to search through objects?

And when were the FragmentBase objects created to be stored into the pageData index? So you reuse objects from the pageData index when you scan the whole HTML page again?

@Abayob Why can’t you use an associative array with objects? If tag is your lookup key, use that as the associative key and a reference to the full object instance as the value. If there is more than one value you want to be able to use for lookup, you can create an associative array for each key. Associative arrays are generally implemented as hash maps, so lookup will be on the order of O(1).

1 Answer 1

I am not very sure about what you want from your question, but here are two methods I can think of, with the objectives to:

About your method: Why did you create the pageData class? Why couldn’t you store them in a dynamic object/associative array? Then create an abstract method getTagType() in the FragmentBase abstract class, with implementations such as:

public function getTagType() : string

So you can, for example, store an object as $pageData[$fragment->getTagType()][] = $fragment; , then given the type from the HTML comment, search for the object from that array.

Another method: What about giving the fragments unique IDs? I cannot elaborate on this since I don’t understand why you need to search for an instance from an array. Is there one corresponding object per fragment (HTML comment)? If that is the case, why not simply put the ID in the comment, then retrieve the object using the ID when you render the page? In this case, it gets even faster because direct numeric key to get from a single-dimensional array is always the fastest method to retrieve an element from an array.

Third method: I think this is really irrelevant with your case here. You can use an in-memory SQL database (such as new SQLite3(«:memory:») ) to create a table that indexes every object (every object needs a unique ID to be a placeholder in the table). Then you can easily use an SQL query to search from the many entries, more efficiently. However, I think that SQLite only improves performance when you are processing a really big amount of data (so that the time to prepare/parse statements is shorter than time for manually searching the data), especially when the data will retain for a long time (so not good for webpage-preprocessing PHP on HTTP servers) because the initialization of the database every time is time-consuming, and the data have to be really frequently reused so as to make the time for preparing statements negligible.

Источник

PHP: find an object in array using attributes array

I’m trying to find an object (Or multiple objects) inside an array using another attributes array i came across this question Find array key in objects array given an attribute value and found great solution, i modified it a bit and end up with this:

//$array = array(object1,object2,object3); //$attributes example array('first_name'=>'value','last_name'=>'value'); function filter_by_key($array, $attributes) < $filtered = array(); foreach($array as $k =>$v) < //if($v->$member != $value) //stuck here $filtered[$k] = $v; > return $filtered; > 

4 Answers 4

array_filter is dedicated method to filter arrays:

function createObject($first, $last) < $object = new StdClass; $object->first_name = $first; $object->last_name = $last; return $object; > $array = array( createObject('value1', 'value1'), createObject('value', 'value')); $attributes = array('first_name'=>'value','last_name'=>'value'); var_dump(array_filter($array, function ($element) use($attributes) < foreach ($attributes as $attribute =>$value) < if (is_object($element) && property_exists($element, $attribute) && $element-> !== $value ) < return false; >> return true; >)); 
array(1) < [1]=>object(stdClass)#4 (2) < ["first_name"]=>string(5) "value" ["last_name"]=> string(5) "value" > > 
//$array = array(object1,object2,object3); //$attributes = array('first_name'=>'value','last_name'=>'value'); $filtered = array_filter($array, // that's the callback function that filters the object function ($e) < global $attributes; // we need to make $attributes // recognizable in the scope foreach($attributes as $k =>$v) < if($e[$k] == $v)< // only if object $e from the array has // the same attribute and same value return true; // add this object to $filtered >> return false; > ); 

Pay attention that get_object_vars see only public attributes. May be more effective ReflectionClass::getProperties.

//$array = array(object1,object2,object3); //$attributes example array('first_name'=>'value','last_name'=>'value'); function filter_by_key($array, $attributes) < $filtered = array(); foreach($array as $obj) < $found = true; $obj_attr = get_object_vars($obj); foreach($attributes as $attr =>$val) < if(!isset($obj_attr[$attr]) || $obj_attr[$attr] != $val)< $found = false; break; >> if($found) < $filtered[$k] = $obj; >> return $filtered; > 

Array ( [945] => member Object ( [id] => 13317 [name] => Test 999 [last_name] => Test 999 ) [54] => member Object ( [id] => 13316 [name] => Manuel [last_name] => Maria parra ) [654] => member Object ( [id] => 13315 [name] => Byron [last_name] => Castillo ) [656] => member Object ( [id] => 13314 [name] => Cesar [last_name] => Vasquez ) )

function filter_by_key($array, $member, $attributes) < $filtered = array(); foreach ($array as $k =>$v) < if (in_array($v->$member, $attributes)) < $filtered[$k] = $v; >> return $filtered; 
$filterd = filter_by_key($array, 'id', array('13316','13317')); 

This question is in a collective: a subcommunity defined by tags with relevant content and experts.

Источник

Php, check if object with property = value exists in array of objects

Yes, in modern PHP you can determine if a specific object property contains a specific value without a classic loop by combining the forces of array_column() (which has evolved to also handle arrays of objects) and in_array() .

$objects = [ (object)['cats' => 2], (object)['dogs' => 2], (object)['fish' => 10], (object)['birds' => 1], ]; $needleField = 'cats'; $needleValue = 2; var_export( in_array($needleValue, array_column($objects, $needleField)) ); // output: true 

The advantage of this technique is the obviously concise syntax. This is a perfectly acceptable approach for relatively small volumes of data.

A possible disadvantage to this technique is that array_column() will be generating a new array of all of values that relate to the $needleField .

In my above demo, array_column() will only generate a single-element array because there is only one cats property in all of the objects. If we were processing a relatively large volume of data, then it would be inefficient to bother collecting all of the qualifying cats values and then run in_array() when only one match is necessary to return true .

For «large» volumes of data where performance is a primary criterion for script design, a classic foreach loop would be a better choice and as soon as an object satisfies the rules, then the loop should be halted via return or break .

function hasPropertyValue(array $objects, $property, $value): bool < foreach ($objects as $object) < if (property_exists($object, $property) && $object-> === $value) < return true; >> return false; > var_export( hasPropertyValue($objects, $needleField, $needleValue) ); 

Источник

Array_search in object array

I have this small search function in my page; $searchWord is the word that I need to look for in my array. The array looks a bit like this:

stdClass Object ( [ActionScopeId] => 181365 [DateChanged] => 0001-01-01T00:00:00 [DateCreated] => 2013-08-20T13:59:33.053 [Description] => Snelheid test [MessageCode] => C0000448220 ) stdClass Object ( [ActionScopeId] => 181364 [DateChanged] => 0001-01-01T00:00:00 [DateCreated] => 2013-08-14T10:08:50.707 [Description] => Test [MessageCode] => C0000448219 ) 

Now, for example; I want to look for the word ‘Test’. When it’s found, I want to print the ActionScopeId and DateCreated with it. This is my code:

$roc = array('relation' => $_SESSION['username']); $rocresponse = $wcfclient->ReadOpenCalls($roc); foreach ($rocresponse->ReadOpenCallsResult as $key => $value) < foreach ($value as $key1 =>$value1)< if (array_search($searchWord,$value1))< echo $value1->ActionScopeId; > > > 

But, the result I get is always empty. What am I doing wrong? I fixed it, when trying to search into an object you can use this function:

 function in_object($val, $obj) < if($val == "")< trigger_error("in_object expects parameter 1 must not empty", E_USER_WARNING); return false; >if(!is_object($obj)) < $obj = (object)$obj; >foreach($obj as $key => $value) < if(!is_object($value) && !is_array($value))< if($value == $val)< return true; >>else < return in_object($val, $value); >> return false; > 
if (in_object($searchWord,$value)) 

Источник

Оцените статью