I have a comma separated string like
$str = "word1,word2,word3";
And i want to make a parent child relationship array from it.
Here is an example:
Try this simply making own function as
$str = "word1,word2,word3";
$res = [];
function makeNested($arr) {
if(count($arr)<2)
return $arr;
$key = array_shift($arr);
return array($key => makeNested($arr));
}
print_r(makeNested(explode(',', $str)));
Demo
function tooLazyToCode($string)
{
$structure = null;
foreach (array_reverse(explode(',', $string)) as $part) {
$structure = ($structure == null) ? $part : array($part => $structure);
}
return $structure;
}
Please check below code it will take half of the time of the above answers:
<?php
$str = "sports,cricket,football,hockey,tennis";
$arr = explode(',', $str);
$result = array();
$arr_len = count($arr) - 1;
$prev = $arr_len;
for($i = $arr_len; $i>=0;$i--){
if($prev != $i){
$result = array($arr[$i] => $result);
} else {
$result = array ($arr[$i]);
}
$prev = $i;
}
echo '<pre>',print_r($result),'</pre>';
Here is another code for you, it will give you result as you have asked :
<?php
$str = "sports,cricket,football,hockey,tennis";
$arr = explode(',', $str);
$result = array();
$arr_len = count($arr) - 1;
$prev = $arr_len;
for($i = $arr_len; $i>=0;$i--){
if($prev != $i){
if($i == 0){
$result = array($arr[$i] => $result);
}else{
$result = array(array($arr[$i] => $result));
}
} else {
$result = array ($arr[$i]);
}
$prev = $i;
}
echo '<pre>',print_r($result),'</pre>';
Related
I'm trying to code Conway look-and-say sequence in PHP.
Here is my code:
function look_and_say ($number) {
$arr = str_split($number . " ");
$target = $arr[0];
$count = 0;
$res = "";
foreach($arr as $num){
if($num == $target){
$count++;
}else{
$res .= $count . $target;
$count = 1;
$target = $num;
}
}
return $res;
}
As I run the function, look_and_say(9900) I am getting value I expected: 2920.
My question is for assigning $arr to be $arr = str_split($number) rather than $arr = str_split($number . " "), the result omits the very last element of the $arr and return 29.
Is it normal to add empty space at the end of the $arr foreach to examine the last element or is there any better way to practice this code - besides regex way.
There are 2 methods I was able to come up with.
1 is to add concatenate at the result after the loop too.
function look_and_say ($number) {
$arr = str_split($number);
$target = $arr[0];
$count = 0;
$res = "";
foreach($arr as $num){
if($num == $target){
$count++;
}else{
$res .= $count . $target;
$count = 1;
$target = $num;
}
}
$res .= $count . $target;
return $res;
}
And the 2nd one is to add another if clause inside the loop and determine the last iteration:
function look_and_say ($number) {
$arr = str_split($number);
$target = $arr[0];
$count = 0;
$res = "";
$i=0;
$total = count($arr);
foreach($arr as $num){
if($i == ($total-1))
{
$count++;
$res .= $count . $target;
}
elseif($num == $target){
$count++;
}else{
$res .= $count . $target;
$count = 1;
$target = $num;
}
$i++;
}
return $res;
}
I want to suggest you other way using two nested while loops:
<?php
function lookAndSay($number) {
$digits = str_split($number);
$result = '';
$i = 0;
while ($i < count($digits)) {
$lastDigit = $digits[$i];
$count = 0;
while ($i < count($digits) && $lastDigit === $digits[$i]) {
$i++;
$count++;
}
$result .= $count . $lastDigit;
}
return $result;
}
$arr['animal'][0] = 'Dog';
$arr['animal'][1] = 'Cat';
From that array basically I need to create a function with the array value parameter and then it gives me the array keys.
For example:
find_index('Cat');
Output :
The result is animal, 1
You could probably do something like
function find_index($value) {
foreach ($arr as $index => $index2) {
$exists = array_search($value, $index2);
if ($exists !== false) {
echo "The result is {$index}, {$exists}";
return true;
}
}
return false;
}
Try this:
$arr['animal'][0] = 'Dog';
$arr['animal'][1] = 'Cat';
function find_index($searchVal, $arr){
return array_search($searchVal, $arr);
}
print_r(find_index('Cat', $arr['animal']));
Consider this Array,
$arr['animal'][] = 'Dog';
$arr['animal'][] = 'Cat';
$arr['insects'][] = 'Insect1';
$arr['insects'][] = 'Insect2';
Here is Iterator Method,
$search = 'InsectSub1';
$matches = [];
$arr_array = new RecursiveArrayIterator($arr);
$arr_array_iterator = new RecursiveIteratorIterator($arr_array);
foreach($arr_array_iterator as $key => $value)
{
if($value === $search)
{
$fill = [];
$fill['category'] = $arr_array->key();
$fill['key'] = $arr_array_iterator->key();
$fill['value'] = $value;
$matches[] = $fill;
}
}
if($matches)
{
// One or more Match(es) Found
}
else
{
// Not Found
}
$arr['animal'][] = 'Dog';
$arr['animal'][] = 'Cat';
$arr['insects'][] = 'Insect1';
$arr['insects'][] = 'Insect2';
$search_for = 'Cat';
$search_result = [];
while ($part = each($arr)) {
$found = array_search($search_for, $part['value']);
if(is_int($found)) {
$fill = [ 'key1' => $part['key'], 'key2' => $found ];
$search_result[] = $fill;
}
}
echo 'Found '.count($search_result).' result(s)';
print_r($search_result);
I have array with show names like this:
$shows = array('morning_show_15_02_2014_part2.mp3',
'morning_show_15_02_2014_part1.mp3',
'morning_show_14_02_2014_part2.mp3',
'morning_show_14_02_2014_part1.mp3',
'morning_show_13_02_2014_part2.mp3',
'morning_show_13_02_2014_part1.mp3');
So the list look like:
morning_show_15_02_2014_part2.mp3
morning_show_15_02_2014_part1.mp3
morning_show_14_02_2014_part2.mp3
morning_show_14_02_2014_part1.mp3
morning_show_13_02_2014_part2.mp3
morning_show_13_02_2014_part1.mp3
This is what i get when i loop the directory.
But the list should look like this:
morning_show_15_02_2014_part1.mp3
morning_show_15_02_2014_part2.mp3
morning_show_14_02_2014_part1.mp3
morning_show_14_02_2014_part2.mp3
morning_show_13_02_2014_part1.mp3
morning_show_13_02_2014_part2.mp3
Still ordered by date, but part 1 is first and then comes part 2.
How can i get this list into right order?
Thank you for any help!
Resolved!
Code is prett nasty but i got what i was looking for:
public function getMp3ListAsJSONArray() {
$songs = array();
$mp3s = glob($this->files_path . '/*.mp3');
foreach ($mp3s as $key => $mp3Source) {
$mp3Source = basename($mp3Source);
$mp3Title = substr($mp3Source, 4);
$mp3Title = substr($mp3Title, 0, -4);
$mp3Title = basename($mp3Source, ".mp3");
$mp3Title = str_replace('_', ' ', $mp3Title);
$mp3Title = ucfirst($mp3Title);
$songs[$key]['title'] = $mp3Title;
$songs[$key]['mp3'] = urldecode($this->files_url . '/' . $mp3Source);
}
rsort($songs);
$pairCounter = 1;
$counter = 0;
foreach ($songs as $key => $value) {
$playlist[$pairCounter][] = $value;
$counter = $counter + 1;
if($counter == 2) {
$pairCounter = $pairCounter + 1;
$counter = 0;
}
}
foreach ($playlist as $show) {
$finalList[] = $show[1];
$finalList[] = $show[0];
}
$finalList = json_encode($finalList);
return $finalList;
}
Output is like i described in the topic.
Try to use array sort
Here is an example for you
http://techyline.com/php-sorting-array-with-unique-value/
You must definitely write your own string comparision function. Remember that you have 2 different comparisons. The first compares the first parts for the filenames as strings. The second part compares the numbers, where 20 comes after 2. This is a natural number sorting for the second part. The third part is after the last dot in the filename. This will be ignored.
<?php
function value_compare($a, $b) {
$result = 0;
$descending = TRUE;
$positionA = strpos($a, 'part');
$positionB = strpos($b, 'part');
if ($positionA === $positionB) {
$compareFirstPart = substr_compare($a, $b, 0, $positionA + 1);
if ($compareFirstPart === 0) {
$length = 0;
$offset = $positionA + strlen('part');
$positionDotA = strrpos($a, '.');
$positionDotB = strrpos($b, '.');
$part2A = '';
$part2B = '';
if ($positionDotA !== FALSE) {
$part2A = substr($a, $offset, $positionDotA);
} else {
$part2A = substr($a, $offset);
}
if ($positionDotB !== FALSE) {
$part2B = substr($b, $offset, $positionDotB);
} else {
$part2B = substr($b, $offset);
}
$result = strnatcmp($part2A, $part2B);
} else {
$result = $compareFirstPart;
if ($descending) {
$result = -$result;
}
}
}
return $result;
}
$shows = array('morning_show_15_02_2014_part2.mp3', 'morning_show_15_02_2014_part1.mp3', 'morning_show_14_02_2014_part2.mp3', 'morning_show_14_02_2014_part1.mp3', 'morning_show_13_02_2014_part2.mp3', 'morning_show_13_02_2014_part1.mp3');
usort($shows, 'value_compare');
var_dump($shows);
?>
I would like to test if the key of an associative array exist in my $_POST.
my $_POST is like that:
$_POST["balle"]["x"] = 5;
$_POST["balle"]["y"] = 5;
$_POST["balle"]["z"] = 5;
or like that by example:
$_POST["p1"][1]["vit"] = 7;
$_POST["p1"][1]["angle"] = 32;
$_POST["p2"][2]["vit"] = 17;
$_POST["p2"][2]["angle"] = 2;
the values don't matter but I must check how are my $_POST keys.
I don't understand how i can test recursivly that because the $_POST can change and have differents forms.
I have try this:
function Check_post($new, $arr)
{
echo "Init<br/>";
$res = true;
if (is_array($new))
{
foreach ($new as $key => $value)
{
if (!in_array($key, $arr))
{
echo "Fail $key";
print_r($arr);
return (false);
}
$res = $res & Check_post($new[$key], $arr[$key]);
}
}
else
$res = in_array($new, $arr);
echo "MY RESULT";
var_dump($res);
return ($res);
}
$b = array();
$b["balle"] = array("x", "y", "z");
$post = array();
$post["balle"] = array();
$post["balle"]["x"] = 50;
$post["balle"]["y"] = 50;
$post["balle"]["z"] = 50;
echo "<pre>";
print_r($b);
echo "</pre><pre>";
print_r($post);
echo "</pre>";
Check_post($b, $post);
but i got "Fail balle". my $post variable is to simulate the real $_POST and for make it easier to test.
EDIT:
The function should work like that:
1) test if "balle" exist in $post
2) "balle" exist so recursive call
3) test if "x" exist in $post["balle"](recursive)
4) test if "y" exist in $post["balle"](recursive)
5) test if "z" exist in $post["balle"](recursive)
6) all existe so $res = true
EDIT:
I finaly editet the whole function:
function Check_post($needle, $haystack)
{
if(is_array($needle)){
foreach ($needle as $key => $element){
$result = true;
if($result = (array_key_exists($key, $haystack) || array_key_exists($element, $haystack))){
$key = (isset($haystack[$key]) ? $key : $element);
if(is_array($haystack[$key]))
$result = Check_post($element, $haystack[$key]);
}
if(!$result){
return false;
}
}
return $result;
}else {
return array_key_exists($needle, $haystack);
}
}
Now it should work as you want it
Example:
$_POST["balle"]["x"] = 5;
$_POST["balle"]["y"] = 5;
$_POST["balle"]["z"] = 5;
$b = array();
$b["balle"] = array("x", "y", "z");
var_dump(Check_post($b, $_POST)); //returns true
$b["balle"] = array("x", "y", "z", "b");
var_dump(Check_post($b, $_POST)); //returns false
The in_array function you're using checks if $key is contained in $arr as a value. If I got you right, you want to check if there is the same key in $arr instead. Use array_key_exists($key, $arr) for this.
Try this
$_POST["p1"][1]["vit"] = 7;
$_POST["p1"][1]["angle"] = 32;
$_POST["p2"][2]["vit"] = 17;
$_POST["p2"][2]["angle"] = 2;
$needle = "2";
$samp = Check_post($_POST,$needle);
echo $samp;
function Check_post($array,$needle)
{
if(is_array($array))
{
foreach($array as $key=>$value)
{
if($key == $needle)
{
echo $key." key exists ";
}
else
{
if(is_array($value))
{
check_post($value,$needle);
}
}
}
}
}
Demo
I need to replace multiple sections of a string based on their indices.
$string = '01234567890123456789';
$replacements = array(
array(3, 2, 'test'),
array(8, 2, 'haha')
);
$expected_result = '012test567haha0123456789';
Indices in $replacements are expected not to have overlaps.
I have been trying to write my own solution, split the original array into multiple pieces based on sections which needs to be replaced or not, and finally combine them:
echo str_replace_with_indices($string, $replacements);
// outputs the expected result '012test567haha0123456789'
function str_replace_with_indices ($string, $replacements) {
$string_chars = str_split($string);
$string_sections = array();
$replacing = false;
$section = 0;
foreach($string_chars as $char_idx => $char) {
if ($replacing != (($r_idx = replacing($replacements, $char_idx)) !== false)) {
$replacing = !$replacing;
$section++;
}
$string_sections[$section] = $string_sections[$section] ? $string_sections[$section] : array();
$string_sections[$section]['original'] .= $char;
if ($replacing) $string_sections[$section]['new'] = $replacements[$r_idx][2];
}
$string_result = '';
foreach($string_sections as $s) {
$string_result .= ($s['new']) ? $s['new'] : $s['original'];
}
return $string_result;
}
function replacing($replacements, $idx) {
foreach($replacements as $r_idx => $r) {
if ($idx >= $r[0] && $idx < $r[0]+$r[1]) {
return $r_idx;
}
}
return false;
}
Is there any more effective way to achieve the same result?
The above solution doesn't look elegant and feels quite long for string replacement.
Use this
$str = '01234567890123456789';
$rep = array(array(3,3,'test'), array(8,2,'haha'));
$index = 0;
$ctr = 0;
$index_strlen = 0;
foreach($rep as $s)
{
$index = $s[0]+$index_strlen;
$str = substr_replace($str, $s[2], $index, $s[1]);
$index_strlen += strlen($s[2]) - $s[1];
}
echo $str;