Php Changing a consecutive array to a inclusive array - php

I am working on a latin website that holds some information in a string this way:
nominative:0:us,a,um;genitive:0:i;dative,ablative:1:is
I would like to turn this information into an array like this
array(
'nominative'=>array(
0=>array('us','a','um')
),
'genitive'=>array(
0=>'i'
)
'dative'=>array(
1=>'is'
)
'ablative'=>array(
1=>'is'
)
)
My current code looks like this
//turn into array for each specification
$specs=explode(';',$specificities);
foreach($specs as $spec):
//turn each specification into a consecutive array
$parts=explode(':',$spec);
//turn multiple value into array
foreach($parts as &$value)
if(strpos($value,',')!==false)
$value=explode(',',$value);
//imbricate into one other
while(count($parts)!==1):
$val=array_pop($parts);
$key=array_pop($parts);
if(is_array($key)):
foreach($key as $k)
$parts[$k]=$val;
else:
$parts[$key]=$val;
endif;
endwhile;
endforeach;
I'm stuck. Help.
Edit: Thanks for the quick responses everybody!
The response I preferred was from CaCtus. I modified it to add flexibility but it was the most useful.
For those interested, here is the new code:
$parts=explode(';','nominative:0:er,ra,rum;genitive:0:i;dative,ablative:1:is;root:r;');
if(!empty($parts)&&!empty($parts[0])):
foreach($parts as $part):
$subpart=explode(':',$part);
$keys=explode(',',$subpart[0]);
foreach($keys as $key):
#$vals=(strpos($subpart[2],',')!==false)
?explode(',',$subpart[2])
:$subpart[2];
$final=(is_null($vals))
?$subpart[1]
:array($subpart[1]=>$vals);
endforeach;
endforeach;
endif;

$string = 'nominative:0:us,a,um;genitive:0:i;dative,ablative:1:is';
$finalArray = array();
// Separate each specification
$parts = explode(';', $string);
foreach($parts as $part) {
// Get values : specification name, index and value
$subpart = explode(':', $part);
// Get different specification names
$keys = explode(',', $subpart[0]);
foreach($keys as $key) {
if (preg_match('#,#', $subpart[2])) {
// Several values
$finalValues = explode(',', $subpart[2]);
} else {
// Only one value
$finalValues = $subpart[2];
}
$finalArray[$key] = array(
$subpart[1] => $finalValues
);
}
}

Would something a little simplier work?
function multiexplode ($delimiters,$string) {
$ready = str_replace($delimiters, $delimiters[0], $string);
$launch = explode($delimiters[0], $ready);
return $launch; }
$input = "0:us,a,um;genitive:0:i;dative,ablative:1:is";
$exploded = multiexplode(array(",",":",";"),$input);
$test = array(
'nominative'=>array(0=>array($exploded[1],$exploded[2],$exploded[3])),
$exploded[4]=>array(0=>$exploded[6]),
$exploded[7]=>array(1=>$exploded[10]),
$exploded[8]=>array(1=>$exploded[10]) );
print_r($test);

Just another alternative:
$specificities = "nominative:0:us,a,um;genitive:0:i;dative,ablative:1:is";
$specificities = trim($specificities, ";") . ";"; //mandatory a trailing ;
$pattern = "/(?<types>[a-z\,]+):(?<ids>\d):(?<values>.*?);/";
preg_match_all($pattern, $specificities, $matches, PREG_SET_ORDER);
$result = array();
array_map(function($item) use (&$result)
{
$types = explode("," , $item['types']);
if(count($types) == 1)
{
$result[$item['types']] = array(
$item['ids'] => explode("," , $item['values'])
);
}
else
{
foreach ($types as $type)
{
$result[$type] = array(
$item['ids'] => explode("," , $item['values'])
);
}
}
}, $matches);
var_dump($result);

Related

Array_intersect and order of values returned

I'm fairly new to PHP and I have a question.
I'm trying to make a function that adds tags to a text.
My function works but the order of the tags in the array returned is wrong.
How can I change the order, please
Thanks for any help.
<?php
$tags = [
'animals' => ['cat', 'dog', 'horse', 'ferret'],
'nature' => ['walk', 'outdoor', 'tree', 'plant']];
function getTags(string $text, array $tags): array
{
$lowerC = strtolower($text);
$str = preg_replace("/[^A-Za-z\'\- ]/", '', $lowerC);
$arrayT = explode(" ", $str);
$tagArray = [];
foreach ($tags as $tag => $value) {
if (array_intersect( $value, $arrayT )) {
$tagArray[] = $tag;
}
} return $tagArray;
}
$res = getTags('During my walk, I met a white horse', $tags);
var_dump($res); // returns ['animals', 'nature'] but I'm trying to get ['nature', 'animals']
If you want to get 'nature' first, because 'walk' comes before 'horse', you need to iterate over the words first, not over the tags.
$tags = [
'animals' => ['cat', 'dog', 'horse', 'ferret'],
'nature' => ['walk', 'outdoor', 'tree', 'plant'],
];
function getTags(string $text, array $tags): array
{
$lowerC = strtolower($text);
$str = preg_replace("/[^A-Za-z\'\- ]/", '', $lowerC);
$arrayT = explode(" ", $str);
$tagArray = [];
foreach ($arrayT as $word) {
// find tag for this word
foreach ($tags as $cat => $values) {
if (in_array($word, $values)) {
// append the tag to the list
$tagArray[] = $cat;
}
}
}
// remove duplicates
return array_unique($tagArray);
}
$res = getTags('During my walk, I met a white horse', $tags);
var_dump($res);
Output :
array(2) {
[0]=>
string(6) "nature"
[1]=>
string(7) "animals"
}
EDIT
As #GeorgeGarchagudashvili mentionned, the code could be optimized by preparing an array for comparison. Here is a way :
function getTags(string $text, array $tags): array
{
$lowerC = strtolower($text);
$str = preg_replace("/[^A-Za-z\'\- ]/", '', $lowerC);
$arrayT = explode(" ", $str);
// Prepare tags for searching
$searchTags = [];
foreach ($tags as $cat => $values) {
foreach ($values as $word) {
$searchTags[$word] = $cat;
}
}
$tagArray = [];
foreach ($arrayT as $word)
{
// find tag for this word
if (isset($searchTags[$word]))
{
// append the tag to the list
$tagArray[] = $searchTags[$word];
}
}
// remove duplicates
return array_unique($tagArray);
}

Convert string containing array elements to array

I have a string that I need to convert to an array.
This is my string that I have in a variable:
$text ='"list_Menu1"=>"root","list_Submenu1"=>"Menu1","list_Submenu2"=>"Menu1","list_Menu2"=>"root",'
And I want to insert it into an array like this:
$tree = array(
"list_Menu1" => "root",
"list_Submenu2" => "list_Menu1",
"list_Submenu3" => "list_Menu1",
"list_Menu2" => "root",);
I tried to generate the array doing this: $tree = array($text), but it doesn't work. How can I do thus, I'm a little lost.
Try this
$text ='"list_Menu1"=>"root","list_Submenu1"=>"Menu1","list_Submenu2"=>"Menu1","list_Menu2"=>"root",';
$text = str_replace("=>",":",$text);
// trim last coma
$text = trim($text,",");
$text = "{".$text."}";
$array = json_decode($text,true);
var_dump($array);
Its a little long shot, but it works too..
function objectToArray($d) {
if (is_object($d)) {
$d = get_object_vars($d);
}
if (is_array($d)) {
return array_map(__FUNCTION__, $d);
}
else {
return $d;
}
}
$text ='"list_Menu1"=>"root","list_Submenu1"=>"Menu1","list_Submenu2"=>"Menu1","list_Menu2"=>"root",';
$text = str_replace("=>",':',$text);
$text = rtrim($text,",");
$text = '{'.$text.'}';
$text = json_decode($text);
$text = objectToArray($text);
print_r($text);
Explode the string by comma (,) and to remove null valued indexes array_filter can be used.
$text ='"list_Menu1"=>"root","list_Submenu1"=>"Menu1","list_Submenu2"=>"Menu1","list_Menu2"=>"root",';
$tree = array_filter( explode(',', $text) );
print '<pre>';
print_r($tree);
print '</pre>';
Hope this helps:-
<?php
function str_to_arr($str) {
$str = str_replace('"',"",$str);
$arr = explode(',',$str);
for($i=0;$i<count($arr);$i++) {
if($arr[$i]!="") {
$tmp_arr = explode('=>',$arr[$i]);
$arr2[$tmp_arr[0]] = $tmp_arr[1];
}
}
return $arr2;
}
$text ='"list_Menu1"=>"root","list_Submenu1"=>"Menu1","list_Submenu2"=>"Menu1","list_Menu2"=>"root",';
$arr = str_to_arr($text);
print_r($arr);
?>
Combination of str_replace and explode will do the trick. Here it is:
$text ='"list_Menu1"=>"root","list_Submenu1"=>"Menu1","list_Submenu2"=>"Menu1","list_Menu2"=>"root"';
$new_text = explode(",", str_replace("\"","", $text));
$new_arr_ = array();
foreach($new_text as $values) {
$new_values = explode("=>", $values);
$new_arr_[$new_values[0]] = $new_values[1];
}
echo '<pre>';
var_dump($new_arr_);
echo '</pre>';

Transform numeric array in associative in order to access it from html template

Alright, my data gets stored in a file using the same pattern:
id|title|content
I created a function which explodes the entries by the delimiter '|' into an array.
function get_entries(){
$retAr = array();
$data = file_get_contents("db/entries.log");
$lines = explode("\n", $data); //create array separate by new line
foreach($lines as $line){
$retAr[] = explode('|', $line );
}
return array_reverse( $retAr );
}
Accessable in html:
<?php foreach(get_entries() as $entry): ?>
<a class='title'><?php echo $entry[1];?></a>
<p class='content'><?php echo $entry[2];?></p>
<?php endforeach; ?>
Okay, it works so far but I want to access the data using an associative array pretty much like this.
<?php foreach(transform_to_assoc(get_entries()) as $entry): ?>
<a class='title'><?php echo $entry['title'];?></a>
<p class='content'><?php echo $entry['content'];?></p>
<?php endforeach; ?>
Related function I've written:
function transform_to_assoc($num_array){
$keys = array('id', 'title', 'content');
$assoc = array();
foreach ($num_array as $data) {
foreach ($keys as $key) {
$assoc[$key] = $data;
}
}
return $assoc;
}
Unfortunately, it does not work. Maybe I got something wrong, but I'm sure my approach was the right one. Help would be appreciated.
That should do what you want:
function transform_to_assoc($num_array){
$keys = array('id', 'title', 'content');
$assoc = array();
foreach ($keys as $k=>$key) {
$assoc[$key] = $num_array[$k];
}
return $assoc;
}
Edit:
To use this for a multi dimensional array do the following:
$arr = array(
array(0, 'test heading 1', 'test content 1'),
array(1, 'test heading 1', 'test content 1'),
);
$newArray = array();
foreach($arr as $a) {
$newArray[] = transform_to_assoc($a);
}
function transform_to_assoc($num_array){
$keys = array('id', 'title', 'content');
$assoc = array();
foreach ($keys as $k=>$key) {
$assoc[$key] = $num_array[$k];
}
return $assoc;
}
You could use the list construct. Just exchange the first foreach loop with this:
foreach($lines as $i => $line){
list($retAr[$i]['id'], $retAr[$i]['title'], $retAr[$i]['content']) = explode('|', $line );
}

Php explode array with specific value

I really need some help with this code and I'm not that good at PHP.
Here is the code:
function projectAttr($number){
global $clerk, $project;
$projectid = $project['id'];
$tags = array();
$cleanUrls= (bool) $clerk->getSetting( "clean_urls", 1 );
$getTags = $clerk->query_select ( "projects_to_tags", "DISTINCT tag", "WHERE projectid='$projectid' ORDER BY id ASC" );
while ( $tag= $clerk->query_fetchArray( $getTags ) )
{
$tagset = explode('; ', $tag['tag']);
}
return html_entity_decode($tagset[$number]);
}
The code explodes a string and puts it in a array, that I can get by projectAttr(0). But I want to be more specific in what I want to get from the string.
This is my string:
size='large'; caption='short text about post/project'; bgcolor='black'; color='white';
What I want is, if I write projectAttr(size) it should return the value large and so forth.
Is that even possible?
Thanks, Peter
I'll answer specifically to the explode you want. You should modify your projectAttr function to look this this:
$items = explode('; ', $string);
$attr = array();
foreach($items as $item) {
list($key, $val) = explode('=', $item);
$attr[$key] = str_replace(array("'", ""), '',$val);
}
Which returns
Array (
[size] => large
[caption] => short text about post/project
[bgcolor] => black
[color] => white
)
EXAMPLE DEMO
So modify your function to look like this:
function projectAttr($name) {
global $clerk, $project;
$projectid = $project['id'];
$tags = array();
$cleanUrls = (bool) $clerk->getSetting("clean_urls", 1);
$getTags = $clerk->query_select("projects_to_tags", "DISTINCT tag", "WHERE projectid='$projectid' ORDER BY id ASC");
while ($tag = $clerk->query_fetchArray($getTags)) {
$items = explode('; ', $string);
$attr = array();
foreach ($items as $item) {
list($key, $val) = explode('=', $item);
$attr[$key] = str_replace(array("'", ""), '', $val);
}
}
return html_entity_decode($attr[$name]);
}
And that should allow you to call it like this:
projectAttr('size');
try
function projectAttr($number){
$str= "size='large'; caption='short text about post/project'; bgcolor='black'; color='white';";
$r = explode('; ', $str);
foreach($r as $k=>$v) {
$attr = explode('=', $v);
$projectAttr[$attr[0]] = str_replace("'", "", $attr[1]);
}
return html_entity_decode($projectAttr[$number]);
}
echo projectAttr('size'); // large

PHP array group by data values

This is my $data variable:
cv = 1,2,3,4,5:::cpt = 4,5 ...
Now I need some function, where I can add the number as param (number will be $data number value).
for example.
function getPermission($id) {
... return $something;
}
Then if I call the function like: echo getPermission(4); it'll print out the data 'keys' where the 4 will be inside, as a value.
So, to be clear:
if I call the function like this:
echo getPermission(4); output will be "cv" and "cpt".
but if I call it this way:
echo getPermission(1);
it'll only output "cv" because number (1) is located in the cv key.
Hope you guys understand, feel free to ask if something aren't clear enough.
$str = 'cv = 1,2,3,4,5:::cpt = 4,5';
$tmp = explode(':::', $str);
$data = array();
foreach ($tmp as $arr) {
$tokens = explode(' = ', $arr);
$data[$tokens[0]] = explode(',', $tokens[1]);
}
print_r(getPermission(4, $data));
print_r(getPermission(1, $data));
function getPermission($id, $data) {
$out = array();
foreach ($data as $key => $arr) {
if (in_array($id, $arr)) $out[] = $key;
}
return $out;
}

Categories