Trying to manipulate an array with PHP - php

I did not want to ask, but I am still quite new to PHP and I am stuck.
I have a comma separated list stored in MySQL; Blue, 12, Red, 15 etc.
I can bring it out and do most of what I want, but I am confused on how to proceed.
Ultimately, I would like to change the output of the data from
Blue, 12, Red, 15,
to
Blue => 12, Red => 15 (without the last comma) So I can use the data in a program I am attempting to build.
Currently, I am able to achieve:
Blue, => 12, => Red, => 15,
Code:
$result = $con->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$id = $row['id'];
$type = $row["dataname"];
$datas = $type;
eval( "\$test = array (" . $datas . ");") ;
foreach($test as $test)
{
echo "<option name='$test'>$test , =></option>";
}
}
}
Using the desired output, I will be able to input data from a form to create an SVGGraph.
Thank you in advance for any assistance.

Ok so first off, I would try storing this information in separate rows in the future, comma separated lists are for when we do not have databases (simple text files for example).
But to answer your question (assuming result is the string of separated values):
$result = explode(',', $result);
$output = [];
for($i = 0;$i < count($result);$i=$i+2){
array_push($output, $result[i] => $result[i+1]);
}
//output:
$str = ""
foreach($output as $key => $value){
str .= $key . ' => ' . $value . ' ,';
}
$str = rtrim($str, ',');
echo $str //this will be your output

using eval is just the worst.
Here is how I would do it while keeping to your code as much as possible:
$result = $con->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$id = $row['id'];
$type = $row["dataname"];
$datas = $type;
$res = array();
$arr = explode(",", str_replace(" ","",$datas));
for ($i = 0; $i < count($arr); $i+=2) {
$res[$arr[$i]] = $arr[$i + 1];
}
foreach($res as $key=>$value)
{
echo "<option name='$value'>$key , =></option>";
}
}
}

First of all, try not to use eval - it is dangerous.:)
Second, try to get all the data you need into one big string. Then you can use the explode PHP function to convert the string into individual elements. And the last thing you would do is to simply iterate over the array and assign the first item as a key and the second item as an element into yet another array.
I will leave the actual implementation to you as an excercise in your PHP coding skills.:)

//trim comma from the right
$str = rtrim('Blue, 12, Red, 15,', ',');
//create a helper array
$array = explode(', ', $str);
//arrange elements in the new array
for ($i = 0; $i < count($array) - 1; $i = $i + 2) {
$new[] = $array[$i] . ' => ' . $array[$i + 1];
}
//output new elements
echo implode(', ', $new);

Please dont use eval. You nearly always can avoid it and is dangerous.
Here is a solution which works without eval:
$result = $con->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$id = $row['id'];
$type = $row["dataname"]; // Thats our comma-seperated list, right?
$arr = explode(',', $type); // Make $type to array
array_pop($arr); // Delete last element because its empty
// We go through the array with step = 2
// because the first is always the key and the second the value
for($i = 0; $i < count($arr); $i += 2)
{
echo "<option name='$arr[$i+1]'>$arr[$i] , =></option>";
}
}
}
Why eval is evil:
Whatever is in the string is evaled as code from your script with all rights the script has incuding file-access and so on. Since the string for your eval comes from the database you cant even be absolutely sure that it is no bad code you are executing when using eval.
Furthermore eval is bad when it comes to debugging things.
And at the end: Why producing overhead with stuff you can avoid?
It is in general recognized as bad style when using eval because of all this reasons. Better you never get used to it

If I understand correctly, you go from a string to an array to a string.
If so, it is possible to skip the array by using regex. Depending on the length of your string, creating a huge array may be a problem.
So I came up with those examples:
$input = "Blue, 1, Red, 2, Green, 3, Violet, 4,";
// Output: Blue => 1, Red => 2, Green => 3, Violet => 4
echo rtrim(preg_replace('/(([^,]*),([^,]*)),+/', '\2 =>\3,', $input), ',');
// Output <option name="Blue">Blue => 1</option><option name="Red">Red => 2</option><option name="Green">Green => 3</option><option name="Violet">Violet => 4</option>
echo preg_replace('/(\s*([^,]*)\s*,\s*([^,]*)\s*),+/', '<option name="\2">\2 => \3</option>', $input);
As you can see, no looping involved.
I hope it helped
EDIT
Here is links to visualize the regex
First regex
Second regex

Related

combine array entries with every other entry

Sorry for the title as it looks like most of the other questions about combining arrays, but I don't know how to write it more specific.
I need a PHP function, which combines the entries of one array (dynamic size from 1 to any) to strings in every possible combination.
Here is an example with 4 entries:
$input = array('e1','e2','e3','e4);
This should be the result:
$result = array(
0 => 'e1',
1 => 'e1-e2',
2 => 'e1-e2-e3',
3 => 'e1-e2-e3-e4',
4 => 'e1-e2-e4',
5 => 'e1-e3',
6 => 'e1-e3-e4',
7 => 'e1-e4'
8 => 'e2',
9 => 'e2-e3',
10 => 'e2-e3-e4',
11 => 'e2-e4',
12 => 'e3',
13 => 'e3-e4',
14 => 'e4'
);
The sorting of the input array is relevant as it affects the output.
And as you see, there should be an result like e1-e2 but no e2-e1.
It seems really complicated, as the input array could have any count of entries.
I don't even know if there is a mathematical construct or a name which describes such a case.
Has anybody done this before?
You are saying that there might be any number of entries in the array so I'm assuming that you aren't manually inserting the data and there would be some source or code entering the data. Can you describe that? It might be easier to directly store it as per your requirement than having an array and then changing it as per your requirement
This might be helpful Finding the subsets of an array in PHP
I have managed to bodge together a code that creates the output you want from the input you have.
I think I have understood the logic of when and why each item looks the way it deos. But Im not sure, so test it carefully before using it live.
I have a hard time explaining the code since it's really a bodge.
But I use array_slice to grab the values needed in the strings, and implode to add the - between the values.
$in = array('e1','e2','e3','e4');
//$new =[];
$count = count($in);
Foreach($in as $key => $val){
$new[] = $val; // add first value
// loop through in to greate the long incrementing string
For($i=$key; $i<=$count-$key;$i++){
if($key != 0){
$new[] = implode("-",array_slice($in,$key,$i));
}else{
if($i - $key>1) $new[] = implode("-",array_slice($in,$key,$i));
}
}
// all but second to last except if iteration has come to far
if($count-2-$key >1) $new[] = Implode("-",Array_slice($in,$key,$count-2)). "-". $in[$count-1];
// $key (skip one) next one. except if iteration has come to far
If($count-2-$key >1) $new[] = $in[$key] . "-" . $in[$key+2];
// $key (skip one) rest of array except if iteration has come to far
if($count-2-$key > 1) $new[] = $in[$key] ."-". Implode("-",Array_slice($in,$key+2));
// $key and last item, except if iteration has come to far
if($count-1 - $key >1) $new[] = $in[$key] ."-". $in[$count-1];
}
$new = array_unique($new); // remove any duplicates that may have been created
https://3v4l.org/uEfh6
here is a modificated version of Finding the subsets of an array in PHP
function powerSet($in,$minLength = 1) {
$count = count($in);
$keys = array_keys($in);
$members = pow(2,$count);
$combinations = array();
for ($i = 0; $i < $members; $i++) {
$b = sprintf("%0".$count."b",$i);
$out = array();
for ($j = 0; $j < $count; $j++) {
if ($b{$j} == '1') {
$out[] = $keys[$j];
}
}
if (count($out) >= $minLength) {
$combinations[] = $out;
}
}
$result = array();
foreach ($combinations as $combination) {
$values = array();
foreach ($combination as $key) {
$values[$key] = $in[$key];
}
$result[] = implode('-', $values);
}
sort($result);
return $result;
}
This seems to work.

how to display a string pattern using php loops

my question is how to display string as a pattern using php loops like, if the string is computer,on first iteration it will display "c" and then second iteration it will display like "co" and so on.My following code given below.please give a solution.
<?php
$array = "computer";
$count = strlen($array);
for($i=0;$i<=$count;$i++)
{
echo $array[$i]."<br>";
}
?>
output will print like this
c
co
com
comp
compu
$array = "computer";
$count = strlen($array);
for($i=0;$i<=$count;$i++)
{
echo substr($array,0,$i+1)."<br>";
}
$array = "computer";
$count = strlen($array)-1;
$out='';
for($i=0;$i<=$count;$i++)
{
$out .= $array[$i];
echo $out."<br>";
}
Have a nice day :-)
You can use substr($array, 0, $i + 1) instead of $array[$i]. Visit to: PHP: substr for more information.

PHP How to merge two arrays inside a loop

I have a problem with the code below which is driving me crazy. What I want to do is to compare a given array with a sentence and then I need to know their position in the sentence for each occurrence, by now the script only return just one array, for example with the positions in which the name Marta is found inside the sentence. I trying to merge all the results in just one array but I'm a bit lost at the moment. I hope someone can give me some clues to make it. Best regards.
$sentence = 'Maria is Maria and Marta is Marta.';
$womennames = array("Maria","Marta");
function poswomen($chain, $words){
foreach($words as $findme){
$valida_existe = substr_count($chain,$findme);
$largo_encuentra = strlen($findme);
$posicion = array();
for($x=0; $x < strlen($chain); $x++){
$posic_x = strpos($chain, $findme, $x);
if($posic_x >= 0){
$posicion[] = $posic_x;
$x = $x+$largo_encuentra;
}
}
$posicion = array_unique($posicion);
$posicion = implode(",",$posicion);
}
return $posicion;
}
poswomen($sentence, $womennames);
print_r (poswomen($sentence, $womennames));
Just like barmar has said, your position keeps resetting you need to set it outside, from that , then add the currently found position so that it will carry on. Consider this example:
$sentence = 'Maria is Maria and Marta is Marta.';
$women_names = array('Maria', 'Marta');
$pos = 0;
$positions = array();
foreach($women_names as $name) {
while (($pos = strpos($sentence, $name, $pos))!== false) {
$positions[$name][] = $pos;
$pos += strlen($name);
}
$positions[$name] = implode(', ', $positions[$name]);
}
echo '<pre>';
print_r($positions);
echo '</pre>';
Sample Output:
Array
(
[Maria] => 0, 9
[Marta] => 19, 28
)

Assign variable to values in array php

This is what I want to do:
Split a word into separate charachters. The input word comes from a form and can differ from each user.
Assign variables to each charachter so that i can manipulate them separately.
Her's my code so far (which doesn't work). Apoligize if ther's a lot of stupid mistakes here, but I am new to PHP.
<?php
$word = $_POST['input'];
//split word into charachters
$arr1 = str_split($word);
//assigning a variable to each charchter
$bokstaver = array();
while($row = $arr1)
{
$bokstaver[] = $row[];
}
$int_count = count($bokstaver);
$i=0;
foreach ($bokstaver as $tecken) {
$var = 'tecken' . ($i + 1);
$$var = $tecken;
$i++;
}
?>
I'd like to end up with as many $tecken variables (With the names $tecken, t$tecken1, $tecken2 etc) as the number of charachters in the input.
All help much appreciated, as always!
You don't need to create separate variables for each letter because you have all the letters in an array. Then you just index into the array to get out each letter.
Here is how I would do it.
//get the word from the form
$word = $_POST['input'];
//split word into characters
$characters = str_split($word);
//suppose the word is "jim"
//this prints out
// j
// i
// m
foreach($characters as $char)
print $char . "\n"
//now suppose you want to change the first letter so the word now reads "tim"
//Access the first element in the array (ie, the first letter) using this syntax
$characters[0] = "t";
I dont think its a good idea, but heres how you do it:
<?php
$input = 'Hello world!';
for($i = 0; $i < strlen($input); $i++) {
${'character' . $i} = $input[$i];
}
why do you want that?
you can just go with:
$word = 'test';
echo $word[2]; // returns 's'
echo $word{2}; // returns 's'
$word{2} = 'b';
echo $word{2}; //returns 'b'
echo $word; // returns 'tebt'
...

"Unfolding" a String

I have a set of strings, each string has a variable number of segments separated by pipes (|), e.g.:
$string = 'abc|b|ac';
Each segment with more than one char should be expanded into all the possible one char combinations, for 3 segments the following "algorithm" works wonderfully:
$result = array();
$string = explode('|', 'abc|b|ac');
foreach (str_split($string[0]) as $i)
{
foreach (str_split($string[1]) as $j)
{
foreach (str_split($string[2]) as $k)
{
$result[] = implode('|', array($i, $j, $k)); // more...
}
}
}
print_r($result);
Output:
$result = array('a|b|a', 'a|b|c', 'b|b|a', 'b|b|c', 'c|b|a', 'c|b|c');
Obviously, for more than 3 segments the code starts to get extremely messy, since I need to add (and check) more and more inner loops. I tried coming up with a dynamic solution but I can't figure out how to generate the correct combination for all the segments (individually and as a whole). I also looked at some combinatorics source code but I'm unable to combine the different combinations of my segments.
I appreciate if anyone can point me in the right direction.
Recursion to the rescue (you might need to tweak a bit to cover edge cases, but it works):
function explodinator($str) {
$segments = explode('|', $str);
$pieces = array_map('str_split', $segments);
return e_helper($pieces);
}
function e_helper($pieces) {
if (count($pieces) == 1)
return $pieces[0];
$first = array_shift($pieces);
$subs = e_helper($pieces);
foreach($first as $char) {
foreach ($subs as $sub) {
$result[] = $char . '|' . $sub;
}
}
return $result;
}
print_r(explodinator('abc|b|ac'));
Outputs:
Array
(
[0] => a|b|a
[1] => a|b|c
[2] => b|b|a
[3] => b|b|c
[4] => c|b|a
[5] => c|b|c
)
As seen on ideone.
This looks like a job for recursive programming! :P
I first looked at this and thought it was going to be a on-liner (and probably is in perl).
There are other non-recursive ways (enumerate all combinations of indexes into segments then loop through, for example) but I think this is more interesting, and probably 'better'.
$str = explode('|', 'abc|b|ac');
$strlen = count( $str );
$results = array();
function splitAndForeach( $bchar , $oldindex, $tempthread) {
global $strlen, $str, $results;
$temp = $tempthread;
$newindex = $oldindex + 1;
if ( $bchar != '') { array_push($temp, $bchar ); }
if ( $newindex <= $strlen ){
print "starting foreach loop on string '".$str[$newindex-1]."' \n";
foreach(str_split( $str[$newindex - 1] ) as $c) {
print "Going into next depth ($newindex) of recursion on char $c \n";
splitAndForeach( $c , $newindex, $temp);
}
} else {
$found = implode('|', $temp);
print "Array length (max recursion depth) reached, result: $found \n";
array_push( $results, $found );
$temp = $tempthread;
$index = 0;
print "***************** Reset index to 0 *****************\n\n";
}
}
splitAndForeach('', 0, array() );
print "your results: \n";
print_r($results);
You could have two arrays: the alternatives and a current counter.
$alternatives = array(array('a', 'b', 'c'), array('b'), array('a', 'c'));
$counter = array(0, 0, 0);
Then, in a loop, you increment the "last digit" of the counter, and if that is equal to the number of alternatives for that position, you reset that "digit" to zero and increment the "digit" left to it. This works just like counting with decimal numbers.
The string for each step is built by concatenating the $alternatives[$i][$counter[$i]] for each digit.
You are finished when the "first digit" becomes as large as the number of alternatives for that digit.
Example: for the above variables, the counter would get the following values in the steps:
0,0,0
0,0,1
1,0,0 (overflow in the last two digit)
1,0,1
2,0,0 (overflow in the last two digits)
2,0,1
3,0,0 (finished, since the first "digit" has only 3 alternatives)

Categories