I have a main array containing the following arrays
(at least 50 different types) :
I'm currently programming in php but i can probably adapt the same functions in java , c# etc...
array('type'=>'x-y','value'=>'12');
array('type'=>'y-z','value'=>'6');
array('type'=>'y-x','value'=>'56');
array('type'=>'z-x','value'=>'19');
array('type'=>'z-y','value'=>'18');
array('type'=>'x-z','value'=>'67');
........
I want to create and traverse a graph for each key and run operations on them e.g :
x-y-z-x : 12 * 6 * 19
x-y-x : 12 * 56
x-z-x : 67 * 19
y-z-y : 6 * 18
.......
I have been trying to run each independently using foreach loops but it won't work for the size of dataset that i have .
Any help would be greatly appreciated. Thanks
The code is in php as required, you can test it as well..
function initData($final, $paths, $values) {
for($i=0; $i<sizeof($final);$i++) {
$path = explode('-', $final[$i]["type"]);
$value = $final[$i]["value"];
array_push($paths, $path);
array_push($values, $value);
}
return [$paths, $values];
}
function getFinalValue($finalPath, $paths, $values) {
$path = explode('-', $finalPath);
$finalValue = 1;
for($i=0;$i<sizeof($path)-1;$i++) {
$stop = $path[$i+1];
$start = $path[$i];
$smallPath = array($start, $stop);
$finalValue *= getValue($smallPath, $paths, $values);
}
return $finalValue;
}
function getValue($smallPath, $paths, $values) {
$value = 0;
for($i=0; $i<sizeof($paths);$i++) {
if($smallPath[0] == $paths[$i][0])
{
if($smallPath[1] == $paths[$i][1]) {
print_r($smallPath);
echo ' ';
$value = $values[$i];
print_r($value);
echo '<br>';
}
}
}
return $value;
}
//Test
function test() {
$a = array('type'=>'x-y','value'=>'12');
$b = array('type'=>'y-z','value'=>'6');
$c = array('type'=>'y-x','value'=>'56');
$d = array('type'=>'z-x','value'=>'19');
$e = array('type'=>'z-y','value'=>'18');
$f = array('type'=>'x-z','value'=>'67');
$paths = [];
$values = [];
$testString = 'x-y-z';
$final = array($a,$b,$c,$d,$e,$f);
$data = initData($final, $paths, $values);
$paths = $data[0];
$values = $data[1];
for ($i=0;$i<sizeof($paths);$i++) {
print_r($paths[$i]);
print_r($values[$i]);
echo '<br>';
}
echo '<br>';
echo '<br>';
$finalValue = getFinalValue($testString, $paths, $values);
echo $testString . '=' . $finalValue;
}
test();
?>
Related
I am designing an application and in my modal came across a strange error
<b>Warning</b>: trim() expects parameter 1 to be string, array given in <b>C:\xampp\htdocs\gurukul\demo2\controller\routemgmt\route_mgmt.php</b> on line <b>7</b><br />
61
As far as I can understand its passing an array instead of string in trim. Below is the modal where its showing the error lies :
<?php
include_once dirname(dirname(dirname(__FILE__))) . "/const.php";
include_once PHP_PATH . "/config1.php";
include_once CONFIG_PATH.'/modal/routemgmt/route_mgmt.php';
function sanitize($input) {
return htmlspecialchars(trim($input));
}
// Sanitize all the incoming data
$sanitized = array_map('sanitize', $_POST);
$reason = $sanitized['reason'];
if($reason == "insert"){
$staffs = [];
$stops = [];
$name = $sanitized['rname'];
$code = $sanitized['rcode'];
$desc = $sanitized['rdesc'];
$vnum = $sanitized['vnum'];
$stf = $_POST['staff'];
$st = isset($_POST['stops'])? $_POST['stops']: [];
$st = [];
// foreach($staffs as $staff){
// $stf[] = array_map('sanitize', $staff);
// }
// if(isset($stops)){
// foreach($stops as $stop){
// $st[] = array_map('sanitize', $stop);
// }
// }
$val = insertRoute($conn,$name, $code, $desc, $vnum, $stf, $stops);
echo $val;
}
if($reason == "view"){
$id = $sanitized['id'];
$val = [];
$val = viewRoute($conn,$id);
echo json_encode($val);
}
if($reason == "edit"){
$stf = [];
$stp = [];
$id = $sanitized['pkid'];
$name = $sanitized['rname'];
$code = $sanitized['rcode'];
$desc = $sanitized['rdesc'];
$vnum = $sanitized['vnum'];
$estaffs = $_POST['estaff'];
$estops = $_POST['estops'];
$edel = $_POST['del'];
foreach($estaffs as $val){
$stf[] = array_map('sanitize', $val);
}
foreach($estops as $val){
$stp[] = array_map('sanitize', $val);
}
$cnt = 0;$n_stp = [];
for($i = 0; $i<sizeof($stp); $i++){
if($stp[$i]['stat'] != "Exist"){
$n_stp[$cnt] = $stp[$i];
$cnt++;
}
}
$val = editValues($conn,$id, $name, $code, $desc, $vnum, $stf, $n_stp, $edel);
echo $val;
}
if($reason == "delRoute"){
$id = $sanitized['id'];
$val = delRoute($conn,$id);
echo $val;
}
Can someone please guide me how can I resolve this ? Tried few debugging steps but didnt get succeded
You could rewrite your sanitize function as:
function sanitize($input) {
if (is_array($input))
return array_map('sanitize', $input);
else
return htmlspecialchars(trim($input));
}
That way it will handle a value passed to it which is an array.
Your $_POST variable probably contains some kind of array. Either figure out what you're posting by checking the output of var_dump($input) inside your sanitize function or change it to this:
function sanitize($input) {
return htmlspecialchars(trim((string) $input));
}
if you just want it to work.
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>';
$variable = "test_company_insurance_llc_chennai_limited_w-8tyu.pdf";
I need to display above the $variable like
Test Company Insurance LLC Chennai Limited W-8TYU.pdf
For that I've done:
$variable = str_replace("_"," ","test_company_insurance_llc_chennai_limited_w-8tyu.pdf");
$test = explode(" ", $variable);
$countof = count($test);
for ($x=0; $x<$countof; $x++) {
if($test[$x] == 'w-8tyu' || $test[$x] == 'llc') {
$test[$x] = strtoupper($test[$x]);
//todo
}
}
I've got stuck in the to-do part.
I will change the specific words to uppercase using strtoupper.
Later, how should I need to merge the array?
Any help will be thankful...
$str_in = "test_company_insurance_llc_chennai_limited_w-8tyu.pdf";
$lst_in = explode("_", $str_in);
$lst_out = array();
foreach ($lst_in as $val) {
switch($val) {
case "llc" : $lst_out[] = strtoupper($val);
break;
case "w-8tyu.pdf" : $lst_temp = explode('.', $val);
$lst_out[] = strtoupper($lst_temp[0]) . "." . $lst_temp[1];
break;
default : $lst_out[] = ucfirst($val);
}
}
$str_out = implode(' ', $lst_out);
echo $str_out;
Not terribly elegant, but perhaps slightly more flexible.
$v = str_replace("_"," ","test_company_insurance_llc_chennai_limited_w-8tyu.pdf");
$acronyms = array('llc', 'w-8tyu');
$ignores = array('pdf');
$v = preg_replace_callback('/(?:[^\._\s]+)/', function ($match) use ($acronyms, $ignores) {
if (in_array($match[0], $ignores)) {
return $match[0];
}
return in_array($match[0], $acronyms) ? strtoupper($match[0]) : ucfirst($match[0]);
}, $v);
echo $v;
The ignores can be removed provided you separate the extension from the initial value.
See the code below. I have printed the output of the code as your expected one. So Run it and reply me...
$variable = str_replace("_"," ","test_company_insurance_llc_chennai_limited_w-8tyu.pdf");
$test = explode(" ", $variable);
$countof = count($test);
for ($x=0; $x<$countof; $x++) {
if($test[$x] == 'llc') {
$test[$x] = strtoupper($test[$x]);
//todo
}elseif($test[$x] == 'w-8tyu.pdf'){
$file=basename($test[$x],'pdf');
$info = new SplFileInfo($test[$x]);
$test[$x] = strtoupper($file).$info->getExtension();
}
else{
$test[$x]=ucfirst($test[$x]);
}
}
echo '<pre>';
print_r($test);
echo '</pre>';
echo $output = implode(" ", $test);
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 want to combine strings in PHP. My script creates every possible combination like below.
$part1 = array('','d','n','s','g');
$part2 = array('a','e','o','oo');
$part3 = array('m','n','s','d','l','t','g','j','p');
$part4 = array('g','p','l','');
$part5 = array('g','p','l');
$part6 = array('a','e','o');
$part7 = array('d','l','r','');
$names = array();
foreach ($part1 as $letter1) {
foreach ($part2 as $letter2) {
foreach ($part3 as $letter3) {
foreach ($part4 as $letter4) {
foreach ($part5 as $letter5) {
foreach ($part6 as $letter6) {
foreach ($part7 as $letter7) {
$names[] = $letter1 . $letter2 . $letter3 . $letter4 . $letter5 . $letter6 . $letter7;
}
}
}
}
}
}
}
But I am not happy with my solution. I is quick and dirty code. Is there a solution wich works with a flexible number of part arrays, so I can extend the script by e.g. $part8 easiely? (without changing the loop construction)
Recursive one:
function buildNames( $parts, $chars = ''){
// Nothing to do, shouldn't happen
if( !count( $parts)){
return array();
}
$names = array();
$part = array_shift( $parts);
// Max level, we can build final names from characters
if( !count( $parts)){
foreach( $part as $char){
$names[] = $chars . $char;
}
return $names;
}
// "We need to go deeper" and build one more level with remembered chars so far
foreach( $part as $char){
$names = array_merge( $names, buildNames( $parts, $chars . $char));
}
return $names;
}
$parts = array( $part1, $part2, $part3, $part4, $part5, $part6, $part7);
$names = buildNames( $parts);
From head, from scratch, comment if something, but idea should be good
You could reduce this problem to six cartesian products:
cartesianProduct($part1,
cartesianProduct($part2,
cartesianProduct($part3,
cartesianProduct($part4,
cartesianProduct($part5,
cartesianProduct($part6, $part7))))));
function cartesianProduct($p1, $p2) {
$ret = array();
foreach($p1 as $l1)
foreach($p2 as $l2)
$ret[] = $l1 . $l2;
return $ret;
}