Why trie is also called "prefix tree"? - data-structures

I was reading this article on Wikipedia and stumbled on the line which says "trie is also called prefix tree".
I know the usage of trie but why is it called "prefix tree"?

As they can be searched by prefixes. You can also reverse the trie and find wildcards: http://phpir.com/tries-and-wildcards.
For example the term academic would be c-i-m-e-d-a-c-a. Using the same
technique as before we can now search for all words that end with a
certain phrase, allowing us to handle wildcards at the beginning of
query terms, e.g. *cademically.
<?php
function buildTries($words) {
$trie = new Trie();
$rtrie = new Trie();
foreach($words as $word) {
$trie->add($word);
$rtrie->add(strrev($word));
}
return array('trie' => $trie, 'rtrie' => $rtrie);
}
function searchTries($search, $tries) {
$terms = explode('*', $search);
if(count($terms) > 2) {
return false;
}
if(strlen($terms[0]) && strlen($terms[0])) {
// middle wildcard
$straight = $tries['trie']->prefixSearch($terms[0]);
$rev = $tries['rtrie']->prefixSearch(strrev($terms[1]));
return array_intersect($straight, reverseArray($rev));
} else if(strlen($terms[1]) ) {
// leading wildcard
return reverseArray($tries['rtrie']->prefixSearch(strrev($terms[1])));
} else {
// trailing wildcard
return $tries['trie']->prefixSearch($terms[0]);
}
}
function reverseArray($keys) {
$return = array();
foreach($keys as $key => $value) {
$return[strrev($key)] = $value;
}
return $return;
}
/* Do some searches */
$words = array(
'adder',
'addled',
'abject',
'agreement',
'astronaut',
'handily',
'happily',
'helpfully'
);
$tries = buildTries($words);
$return = searchTries('h*ly', $tries);
var_dump($return);
$return = searchTries('ha*ly', $tries);
var_dump($return);
?>
The results from the two var dumps look like this:
array(3) {
["handily"]=>
NULL
["happily"]=>
NULL
["helpfully"]=>
NULL
}
array(2) {
["handily"]=>
NULL
["happily"]=>
NULL
}

Related

How to add another array value in codeigniter using getRecords

The orignial code was like this , I want to get landline_no value also in getRecords, How to do that
public function checklead() {
$lead = $_POST['number'];
$check = $this->common_model->getRecords('leads',array("phone_no"=>$lead));
if(count($check) > 0) {
$lead = $this->common_model->getRecored_row('leads',array("phone_no"=>$lead));
if($lead->assignto_self != 0) {
$assignto = $lead->assignto_self;
$key = 'Self Assign';
} else if($lead->assignto_se != 0) {
$assignto = $lead->assignto_se;
$key = '';}
What I have achieved so far,but not getting array values from getRecords
$lead = $_POST['number'];
$check = $this->common_model->getRecords('leads',array("phone_no"=>$lead),array("landline_no"=>$lead));
//echo "<pre>";
//print_r($check);
//echo $check[0]['landline_no'];exit;
if(count($check) > 0) {
$lead = $this->common_model->getRecored_row('leads',array("phone_no"=>$lead,"landline_no"=>$check[0]['landline_no']));
Code for getRecords:
function getRecords($table,$db = array(),$select = "*",$ordercol = '',$group = '',$start='',$limit=''){
$this->db->select($select);
if(!empty($ordercol)){
$this->db->order_by($ordercol);
}
if($limit != '' && $start !=''){
$this->db->limit($limit,$start);
}
if($group != ''){
$this->db->group_by($group);
}
$q=$this->db->get_where($table, $db);
return $q->result_array();
}
// Get Recored row
public function getRecored_row($table,$where)
{
$q = $this->db->where($where)
->select('*')
->get($table);
return $q->row();
}
Check my answer: This code also working well, i have written, but i am not sure , this logic is correct or not kindly check this one.
public function checklead() {
$lead = $_POST['number'];
if($this->common_model->getRecords('leads',array("phone_no"=>$lead)))
{
$check=$this->common_model->getRecords('leads',array("phone_no"=>$lead));
}
else
{
$check=$this->common_model->getRecords('leads',array("landline_no"=>$lead));
}
echo "<pre>";
//echo $check;
//print_r($check); exit;
$p= $check[0]['phone_no'];
$l= $check[0]['landline_no'];
// exit;
if(count($p) > 0 || count($l)>0) {
$lead = $this->common_model->getRecored_row('leads',array("phone_no"=>$p));
$lead1 = $this->common_model->getRecored_row('leads',array("landline_no"=>$l));
if($lead->assignto_self != 0 || $lead1->assignto_self != 0) {
$assignto = $lead->assignto_self;
$key = 'Self Assign';
} else if($lead->assignto_se != 0 || $lead1->assignto_se != 0) {
$assignto = $lead->assignto_se;
$key = '';
}else if($lead->assignto_tl != 0 || $lead1->assignto_tl != 0) {
$assignto = $lead->assignto_tl;
$key = '';
} else if($lead->uploaded_by != 0 || $lead1->uploaded_by != 0) {
$assignto = $lead->uploaded_by;
$key = 'Uploaded by';
}
$user = $this->common_model->getRecored_row('admin',array("id"=>$assignto));
$role = $this->common_model->getRecored_row('role',array("id"=>$user->role));
$this->session->set_flashdata('message', array('message' => 'This Lead Already exist with '.$user->name.' ('.$role->role.') '.' ','class' => 'danger'));
redirect(base_url().'leads');
} else {
redirect(base_url().'leads/add_newlead/'.$lead);
}
}
There does not seem to be any reason to use getRecords(). The $check value has no useful purpose and creating it is a waste of resources.
We don't need $check because getRecord_row() will return the "lead" if found so the only check needed is to see if getRecord_row() returns anything. getRecord_row() uses the database function row() which returns only one row or null if no rows are found. Read about row() here.
If what you want is to find the "lead" that has either a "phone_no" or a "landline_no" equal to $_POST['number'] then you need to use a custom string for the where clause. (See #4 at on this documentation page.) You need a custom string because getRecord_row() does not allow any other way to ask for rows where a='foo' OR b='foo'. Here is what I think you are looking for.
public function checklead()
{
// use input->post() it is the safe way to get data from $_POST
$phone = $this->input->post('number');
// $phone could be null if $_POST['number'] is not set
if($phone)
{
$lead = $this->common_model->getRecored_row('leads', "phone_no = $phone OR landline_no = $phone");
// $lead could be null if nothing matches where condition
if($lead)
{
if($lead->assignto_self != 0)
{
$assignto = $lead->assignto_self;
$key = 'Self Assign';
}
else if($lead->assignto_se != 0)
{
$assignto = $lead->assignto_se;
$key = '';
}
}
}
}
The main difference between getRecords() and getRecord_row() is the number of records (rows of data) to return. getRecord_row() will return a maximum of one record while getRecords() might return many records.
getRecords() accepts arguments that allow control of what data is selected ($db, $select), how it is arranged ($ordercol, $group), and the number of rows to retrieve ($limit) starting at row number x ($start) .

doctrine query with parameters having multiple values

I want to make a doctrine query in which each parameters can have multiple values (coming from a select multiple).
I have a table with a 'type' parameter that can have value of 1, 2, 3 or 4 and an 'online' parameter that can be 0 or 1.
My query so far is the following :
$query = $this->createQueryBuilder('properties');
if (array_key_exists('type', $searchValues)) {
$types = $searchValues['type'];
$iterator = 0;
foreach ($types as $type) {
if ($iterator == 0) {
$query->andWhere('properties.idPropertyType = ' . $type);
} else {
$query->orWhere('properties.onlineProperties = ' . $type);
}
$iterator++;
}
}
if (array_key_exists('status', $searchValues)) {
$status = $searchValues['status'];
$iterator = 0;
foreach ($status as $statu) {
if ($iterator == 0) {
$query->andwhere('properties.onlineProperties = ' . $statu);
} else {
$query->andWhere('properties.onlineProperties = ' . $statu);
}
$iterator++;
}
}
$properties = $query->getQuery()->getResult();
In the case of a search with parameter type = 1 and online = 0 and 1, I have results where type is another value than 1. I understand the reason why but I cannot figure out a proper way to make my query.
You don't need to build your query by hand manually, just use the (in) function from the QueryBuilder class. Try this:
$query = $this->createQueryBuilder('properties');
if(array_key_exists('type', $searchValues)){
$types = $searchValues['type'];
$query->andWhere($query->expr()->in('properties.idPropertyType', $types));
}
if(array_key_exists('status', $searchValues)){
$status = $searchValues['status'];
$query->andwhere($query->expr()->in('properties.onlineProperties', $status));
}
$properties = $query->getQuery()->getResult();

Phalcon use Oracle views

In a Phalcon project, I have multiple database in Oracle and mySQL with number of tables and views. Created models for corresponding tables and views. But unable to access views. I initialize in model below:
public function initialize()
{
$this->setConnectionService('dbBznes');
$this->setSchema('POLICY');
$this->setSource("BUSINESS_ALL");
}
As per the comments, this is apparently a metadata issue and the default metadata strategy is introspection and is attempting to check if the table exists. You can set up your own metadata strategy like so:
$di['modelsMetadata'] = function()
{
$metadata = new \Phalcon\Mvc\Model\MetaData\Memory();
$metadata->setStrategy(
new MyIntrospectionStrategy()
);
return $metadata;
};
"Memory" in this case means don't use any sort of metadata caching. This goes off into another tangent as you can cache in many ways for more speed in production, etc.
As for the MyIntrospectionStrategy class above, it represents your own class based on Phalcon's Introspection strategy which attempts to analyze the database to figure out the fields and their types involved with the table.
I believe I converted Phalcon\Mvc\Model\MetaData\Strategy\Introspection from Zephir to PHP correctly as follows:
class MyIntrospectionStrategy implements \Phalcon\Mvc\Model\MetaData\StrategyInterface
{
public final function getMetaData(\Phalcon\Mvc\ModelInterface $model, \Phalcon\DiInterface $dependencyInjector)
{
$schema = $model->getSchema();
$table = $model->getSource();
$readConnection = $model->getReadConnection();
if( !$readConnection->tableExists($table, $schema) )
{
if($schema)
{
$completeTable = $schema . "'.'" . $table;
} else {
$completeTable = $table;
}
throw new \Phalcon\Mvc\Model\Exception(
"Table '" . $completeTable . "' doesn't exist in database when dumping meta-data for " . get_class($model)
);
}
$columns = $readConnection->describeColumns($table, $schema);
if( !count($columns) )
{
if($schema)
{
$completeTable = $schema . "'.'" . $table;
} else {
$completeTable = $table;
}
/**
* The table not exists
*/
throw new \Phalcon\Mvc\Model\Exception(
"Cannot obtain table columns for the mapped source '" . completeTable . "' used in model " . get_class(model)
);
}
$attributes = [];
$primaryKeys = [];
$nonPrimaryKeys = [];
$numericTyped = [];
$notNull = [];
$fieldTypes = [];
$fieldBindTypes = [];
$automaticDefault = [];
$identityField = false;
$defaultValues = [];
$emptyStringValues = [];
foreach($columns as $column)
{
$fieldName = $column->getName();
$attributes[] = $fieldName;
if ($column->isPrimary() === true)
{
$primaryKeys[] = $fieldName;
} else {
$nonPrimaryKeys[] = $fieldName;
}
if ($column->isNumeric() === true)
{
$numericTyped[$fieldName] = true;
}
if ($column->isNotNull() === true)
{
$notNull[] = $fieldName;
}
if ($column->isAutoIncrement() === true)
{
$identityField = $fieldName;
}
$fieldTypes[$fieldName] = $column->getType();
$fieldBindTypes[$fieldName] = $column->getBindType();
$defaultValue = $column->getDefault();
if ($defaultValue !== null || $column->isNotNull() === false)
{
if ( !$column->isAutoIncrement() )
{
$defaultValues[$fieldName] = $defaultValue;
}
}
}
return [
\Phalcon\Mvc\Model\MetaData::MODELS_ATTRIBUTES => $attributes,
\Phalcon\Mvc\Model\MetaData::MODELS_PRIMARY_KEY => $primaryKeys,
\Phalcon\Mvc\Model\MetaData::MODELS_NON_PRIMARY_KEY => $nonPrimaryKeys,
\Phalcon\Mvc\Model\MetaData::MODELS_NOT_NULL => $notNull,
\Phalcon\Mvc\Model\MetaData::MODELS_DATA_TYPES => $fieldTypes,
\Phalcon\Mvc\Model\MetaData::MODELS_DATA_TYPES_NUMERIC => $numericTyped,
\Phalcon\Mvc\Model\MetaData::MODELS_IDENTITY_COLUMN => $identityField,
\Phalcon\Mvc\Model\MetaData::MODELS_DATA_TYPES_BIND => $fieldBindTypes,
\Phalcon\Mvc\Model\MetaData::MODELS_AUTOMATIC_DEFAULT_INSERT => $automaticDefault,
\Phalcon\Mvc\Model\MetaData::MODELS_AUTOMATIC_DEFAULT_UPDATE => $automaticDefault,
\Phalcon\Mvc\Model\MetaData::MODELS_DEFAULT_VALUES => $defaultValues,
\Phalcon\Mvc\Model\MetaData::MODELS_EMPTY_STRING_VALUES => $emptyStringValues
];
}
public final function getColumnMaps(\Phalcon\Mvc\ModelInterface $model, \Phalcon\DiInterface $dependencyInjector)
{
$orderedColumnMap = null;
$reversedColumnMap = null;
if (method_exists($model, 'columnMap'))
{
$userColumnMap = $model->columnMap();
if ( gettype($userColumnMap) != 'array')
{
// Bad grammer directly in cphalcon :sadface:
throw new \Phalcon\Mvc\Model\Exception('columnMap() not returned an array');
}
$reversedColumnMap = [];
$orderedColumnMap = $userColumnMap;
foreach($userColumnMap as $name => $userName)
{
$reversedColumnMap[$userName] = $name;
}
}
return [$orderedColumnMap, $reversedColumnMap];
}
}
I have not tested this.
As far as adding support for views to be treated like tables, the change might be as simple as:
Before:
if( !$readConnection->tableExists($table, $schema) )
After:
if( !$readConnection->tableExists($table, $schema) && !$readConnection->viewExists($table, $schema) )
If this doesn't work due to logic choking with describeColumns, you might need to write something specific for working with views in Oracle for this dialect.
As far as other solutions, you can provide your own metadata method directly on the model by specifying your ownmetaData method directly on it.
Another solution is to use annotations instead of introspection for metadata.
Then you'd place your metadata as comments in the code for Phalcon to parse.
If you continue to run into problems with Database Views, just run it as raw SQL rather than attempting to use the ORM to do it. You can simply define a new method on your model to run the raw SQL.

Modify the MY_Router.php file for QUERY STRING Codeigniter 3.0.6

I use codeigniter 3.0.6 query string like
index.php?d=directoryt&c=controller
index.php?d=directory&c=controller&m=function
How ever having two get methods for directory and controller is a bit long.
Question Is there any way to modify the protected function
_set_routing() function using a MY_Router.php to get it so it will pick up the directory and controller by using one query only like example below.
index.php?route=directory/controller
// If need to get function
index.php?route=directory/controller&m=function
What have tried so far
<?php
class MY_Router extends CI_Router {
protected function _set_routing()
{
// Load the routes.php file. It would be great if we could
// skip this for enable_query_strings = TRUE, but then
// default_controller would be empty ...
if (file_exists(APPPATH.'config/routes.php'))
{
include(APPPATH.'config/routes.php');
}
if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
}
// Validate & get reserved routes
if (isset($route) && is_array($route))
{
isset($route['default_controller']) && $this->default_controller = $route['default_controller'];
isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];
unset($route['default_controller'], $route['translate_uri_dashes']);
$this->routes = $route;
}
// Are query strings enabled in the config file? Normally CI doesn't utilize query strings
// since URI segments are more search-engine friendly, but they can optionally be used.
// If this feature is enabled, we will gather the directory/class/method a little differently
if ($this->enable_query_strings)
{
// If the directory is set at this time, it means an override exists, so skip the checks
if ( ! isset($this->directory))
{
$_route = isset($_GET['route']) ? trim($_GET['route'], " \t\n\r\0\x0B/") : '';
if ($_route !== '')
{
echo $_route;
$this->uri->filter_uri($_route);
$this->set_directory($_route);
}
}
// Routing rules don't apply to query strings and we don't need to detect
// directories, so we're done here
return;
}
// Is there anything to parse?
if ($this->uri->uri_string !== '')
{
$this->_parse_routes();
}
else
{
$this->_set_default_controller();
}
}
}
config.php
$config['allow_get_array'] = TRUE;
$config['enable_query_strings'] = TRUE;
$config['controller_trigger'] = 'c';
$config['function_trigger'] = 'm';
$config['directory_trigger'] = 'd';
// Modifyed in MY_Router.php
$config['route'] = 'route';
I have it working
<?php
class MY_Router extends CI_Router {
protected function _set_routing() {
if (file_exists(APPPATH.'config/routes.php'))
{
include(APPPATH.'config/routes.php');
}
if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
}
// Validate & get reserved routes
if (isset($route) && is_array($route))
{
isset($route['default_controller']) && $this->default_controller = $route['default_controller'];
isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];
unset($route['default_controller'], $route['translate_uri_dashes']);
$this->routes = $route;
}
if ($this->enable_query_strings) {
if ( ! isset($this->directory))
{
$route = isset($_GET['route']) ? trim($_GET['route'], " \t\n\r\0\x0B/") : '';
if ($route !== '')
{
$part = explode('/', $route);
$this->uri->filter_uri($part[0]);
$this->set_directory($part[0]);
if ( ! empty($part[1])) {
$this->uri->filter_uri($part[1]);
$this->set_class($part[1]);
// Testing function atm
if ( ! empty($_GET['function']))
{
$this->uri->filter_uri($_GET['function']);
$this->set_method($_GET['function']);
}
$this->uri->rsegments = array(
1 => $this->class,
2 => $this->method
);
}
} else {
$this->_set_default_controller();
}
}
// Routing rules don't apply to query strings and we don't need to detect
// directories, so we're done here
return;
}
// Is there anything to parse?
if ($this->uri->uri_string !== '')
{
$this->_parse_routes();
}
else
{
$this->_set_default_controller();
}
}
}

Filtering Eloquent Collection

Trying to filter a collection object down based upon any combination of multiple values. This is as far as I've got. Not happening. Any clues for me?
public function search()
{
$posts = Posting::all();
$type_id = Input::get('type_id');
$country_id = Input::get('country_id');
$province_id = Input::get('province_id');
$posts = $posts->filter(function($post)
{
if( !empty($type_id) && $type_id>0 )
{
return $post->where('type_id','=',$type_id);
}
})->values();
$posts = $posts->filter(function($post)
{
if( !empty($country_id) && $country_id>0 )
{
return $post->where('country_id','=',$country_id);
}
})->values();
$posts = $posts->filter(function($post)
{
if( !empty($province_id) && $province_id>0 )
{
return $post->where('province_id','=',$province_id);
}
})->values();
return $posts;
}
Any help appreciated.
First off, you should really do a validation for the id being larger than 0, if they were provided. You shouldn't be manually checking that out.
But anyhow, why are you using filter, when you can just directly use Eloquent (I omitted the check for id being bigger than 0):
$type_id = Input::get('type_id');
$country_id = Input::get('country_id');
$province_id = Input::get('province_id');
$query = Posting::query();
if ( ! empty($type_id)) $query->whereTypeId($type_id);
if ( ! empty($country_id)) $query->whereCountryId($country_id);
if ( ! empty($province_id)) $query->whereProvinceId($province_id);
return $query->get();
First off, you need to return something that makes sense from the closure in your filter:
$posts = $posts->filter(function($post)
{
if( !empty($type_id) && $type_id>0 )
{
return $post->where('type_id','=',$type_id);
}
})
Above returns Eloquent\Builder object, which is evaluated to true, so.. it really doesn't make sense.
This is what you need:
$posts = $posts->filter(function($post)
{
if( !empty($type_id) && $type_id>0 )
{
return $post->type_id == $type_id; // bool
}
})
With such code, you will filter the collection. $posts now will hold only those items, that match the statement in that closure.

Resources