I have a code in which foreach inside another foreach.
$order_id = '1,1,8';
$order_no_first= 'F,SH,C';
$order_id1 = explode(",", $order_id);
$order_no_first1 = explode(',', $order_no_first);
foreach($order_id1 as $ord_id){
foreach($order_no_first1 as $ord_no_first){
if($ord_id != '') {
$this->receipt->chageBagStatus($ord_id, $ord_no_first);
$add = $this->receipt->addJobOrderNew($ord_id, $ord_no_first, $bag_no);
}
}
}
Now the above code iterates 3 times resulting 9 rows in mysql.
//Current Output
order_id orderr_no_first
-------- ---------------
8 C
8 SH
8 F
1 C
1 SH
1 F
1 C
1 SH
1 F
The above output is wrong. I want the output as below,
//Required Output
order_id orderr_no_first
-------- ---------------
8 C
1 SH
1 F
I know it's because am using nested foreach. but I don't know how to solve this issue. Is there any solution. Thankyou.
just use one foreach like this,
foreach($order_id1 as $key => $ord_id){
if($ord_id != '') {
$this->receipt->chageBagStatus($ord_id, $order_no_first1[$key]);
$add = $this->receipt->addJobOrderNew($ord_id, $order_no_first1[$key], $bag_no);
}
}
I hope this will work for you
$order_id = '1,1,8';
$order_no_first= 'F,SH,C';
$order_id1 = explode(",", $order_id);
$order_no_first1 = explode(',', $order_no_first);
rsort($order_id1);
asort($order_no_first1);
$i = 0;
foreach($order_id1 as $ord_id){
echo $ord_id." ".$order_no_first1[$i]."<br/>";
$i++;
}
`
Related
Here is my code:
$answer = explode(" ", $row2['answer']);
foreach($tags as $i =>$key) {
$i >0;
echo $i.' '.$key .'</br>';
}
the output is
0 a
1 b
2 c
3 d
4 e
5 f
I'd like that the output be random, but doesn't repeat twice.
For example:
e 4
a 0
c 2
f 5
d 3
b 1
Any idea please ?
Thank you.
The simplest way I can think of to achieve this would be to use the shuffle method on an array collection. This however does not guarantee non-sequentialness:
$range = range(1,5);
shuffle($range);
foreach($range as $int){
echo $int;
}
I need help writing the logic of the php script which sorts data into a certain format...
Firstly the script needs to loop through each s1 value and ping an endpoint to get the ml values (more like) which are actually referencing other s1 records. this is the easy part! the data is returned like so;
Table 1
s1 | ml
----------
1 | -
2 | 3,4
3 | 2,8,9
4 | -
5 | 2
6 | 1
7 | 10
8 | -
9 | -
10 | -
Condition 1: As you can see the endpoint returns data for the s1 value telling it other s1 records are similar to other ones, but the direction of ml is not always bidirectional. sometimes, like when s1=6 the ml value is 1 however when s1=1 there isn't a ml value.
Condition 2: Again just to explain the ml records, look above and below where s1=5 (above) and where s1=2 + rec=5 (below), this script needs to realise there is already an s1 record for it's value and that it should be added there.
Condition 3: Note how when s1=2,ml=3 this is stored but when s1=3,ml=2 this is ignored because we have the reverse record.
I basically want to match all the data into 1 sorted 'profile' so it ends up in the below format which i will store in another db table of 'sorted' records.
Table 2
s1 | rec
----------
2 | 3
2 | 4
2 | 8
2 | 9
2 | 9
2 | 5
6 | 1
7 | 10
This has been racking my brains for days now, I need something thats efficient because in the end it will deal with millions of records and I'm sure there is an easy solution but i just can't figure how to start it.
I tried the following, but I'm stuck and don't know how to go further;
public function getrelated($id='', $t=''){
if($id != ""){
$get = Easytest::where('s1','=',$id)->get();
if(count($get) > 0){
$ret= array();
foreach($get as $go){
$v = explode(",", $go->s2);
foreach ($v as $e) {
if($e != $t){
$ret[$e] = $this->getrelated($e, $id);
}
}
}
if(count($ret) > 0){
return $ret;
}else{
return "";
}
}else{
return $id;
}
}else{
return "";
}
}
public function easytest(){
ob_start();
$a = array(
array("s1"=>1,"s2"=>implode(",",array()).""),
array("s1"=>2,"s2"=>implode(",",array(3,4)).","),
array("s1"=>3,"s2"=>implode(",",array(2,8,9)).","),
array("s1"=>4,"s2"=>implode(",",array()).""),
array("s1"=>5,"s2"=>implode(",",array(2)).","),
array("s1"=>6,"s2"=>implode(",",array(1)).","),
array("s1"=>7,"s2"=>implode(",",array(10)).","),
array("s1"=>8,"s2"=>implode(",",array()).""),
array("s1"=>9,"s2"=>implode(",",array()).""),
array("s1"=>10,"s2"=>implode(",",array()).""),
array("s1"=>11,"s2"=>implode(",",array(12)).","),
array("s1"=>12,"s2"=>implode(",",array(2)).",")
);
//return Easytest::insert($a);
$records = Easytest::all();
foreach ($records as $record) {
$id = $record->s1;
echo "ROW: ".$id." > ";
$record->s2 = ltrim($record->s2,",");
$ml = explode(",",$record->s2);
if(count($ml) >= 1){
foreach ($ml as $t) {
echo "RESULT: ".$t." -".print_r($this->getrelated($t, $id), true);
echo ",\n";
}
}
echo " <br><br>\n\n";
}
return ob_get_clean();
}
Ok, so I eventually solved this... esentially this is the code below;
improvements welcome :)
You need to call the function like so
related(array('searched'=>array(),'tosearch'=>array(13)));
function:
public function related($input){
$searched = $input['searched'];
$ar = array();
$bits = array();
if(count($input['tosearch']) != 0){
$get = Easytest::orWhere(function($query) use ($input)
{
foreach ($input['tosearch'] as $k=>$v) {
$query->orWhere('s2', 'LIKE', '%,'.$v.',%')->orWhere('s1', '=', $v);
}
})
->orderBy('s1', 'ASC')->get();
foreach ($input['tosearch'] as $k=>$v) {
unset($input['tosearch'][$k]);
$input['searched'][$v] = $v;
}
foreach ($get as $result) {
$thesebits = explode(",", trim($result->s2,","));
foreach ($thesebits as $smallbit) {
if($smallbit != ""){
$bits[] = $smallbit;
}
}
$bits[] = $result->s1;
$bits = array_unique($bits);
foreach ($bits as $k=>$v) {
if(($key = array_search($v, $input['searched'])) == false) {
$input['tosearch'][$v] = $v;
}else{
unset($input['tosearch'][$v]);
}
}
$input['tosearch'] = array_unique($input['tosearch']);
}
return $this->related($input);
}else{
return $input;
}
}
I have a database which has 6 column A B C D E X, for each combination of ABCDE I have a different value of X.
I need a way to search through, that will allow all values of X for different combinations (for example all X when A=1, or all X when A=1 and B=2 etc)
My thought was to translate it into a 5-D array which looks like this:
Array[A][B][C][D][E]=X;
But now I'm trying to extract sub arrays, when I don't know how may of the dimensions will be constant. So I need to be able to extract all value of X for Array[1][5][][][] or Array[2][4][5][][]… etc.
And I'm totally stuck.
I'm trying to do 6 loops one inside another but I don't know how to handle those that are constant.
Help with ideas will be very very helpful.
Edit
Database:
A B C D E X
1 1 1 1 1 53
1 1 2 3 2 34
2 1 1 4 2 64
Turned it into an array:
Array[1][1][1][1][1]=53
Array[1][1][2][3][2]=34
For
Input: A=1
Output 53,34
Input A=1,B=1,C=1
Output: 53,
etc
Try this then
<?php
$arr = array();
$result = mysql_query("SELECT A,B,C,D,E,X FROM table_name ORDER BY A ASC,B ASC,C ASC,D ASC,E ASC");
if(mysql_num_rows($result) > 0) {
while($row = mysql_fetch_assoc($result)) {
array_push($arr,$row);
}
}
function search($arr,$values) {
$return = array();
foreach($arr AS $key => $value) {
$ok = true;
foreach(array('A','B','C','D','E') AS $letter) {
if(array_key_exists($letter,$values)) {
if($value[$letter] != $values[$letter]) {
$ok = false;
break;
}
}
}
if($ok) array_push($return,$value['X']);
}
return (($return) ? implode(',',$return) : false);
}
echo '<pre>';
print_r(search($arr,array('A' => 1)));
echo '</pre>';
?>
Program:
while($i<=$row) {
echo $arr[$i][1].$arr[$i][4]
}
Output
Product Code Qty
KC_DRINK_TASTY_CASE 1
KC_DRINK_TASTY_CASE 1
KC_DRINK_TASTY_CASE 1
KC_DRINK_TASTY_CASE 1
KC_SUNGLASSES_BK 1
KC_SUNGLASSES_BK 1
KC_SUNGLASSES_BE 1
KC_SUNGLASSES_BE 1
KC_SUNGLASSES_OE 1
KC_SUNGLASSES_OE 1
KC_SUNGLASSES_RD 1
KC_SUNGLASSES_RD 1
KC_SUNGLASSES_WE 1
KC_SUNGLASSES_WE 1
I want it to output
KC_DRINK_TASTY_CASE 4
KC_SUNGLASSES 10
so that it group product code excluding last underscore and sum their quantity
If $arr looks something like this:
$arr = array(
array('{something}', 'KC_DRINK_TASTY_CASE', '{something}', '{something}', 1),
array('{something}', 'KC_SUNGLASSES_BK', '{something}', '{something}', 1),
// ...
);
Then you can get the output what you what like this:
// we'll store counts here
$result = array();
foreach ($arr as $row) {
$product = $row[1];
$qty = $row[4];
// figure out where the last underscore is and chop off everything that follows it
// this is VERY brittle. If the product ends up with a name like _SOMEKEY you'll end
// up with an empty key. Not good. Probably not a huge issue, but buyer beware
$_product = substr($product, 0, strrpos($product, '_'));
if (isset($result[$_product])) {
$result[$_product] += $qty; // we already started counting
} else {
$result[$_product] = $qty; // not started counting this product yet, start it
}
}
// now print your result:
foreach ($result as $id => $qty) {
echo $id, "\t", $qty, PHP_EOL;
}
My question might be a bit vague, because I cannot quite figure it out.
I have a piece of PHP that tries to convert a mysql query result into an array "tree".
I.e. arrays of arrays depending on the defined groups.
The code assumes that a column name would start with a double underscore __ to indicate grouping and the results will already be ordered by the grouping.
The code works , but in certain cases it slows down to unusable speeds.
Cases which I would expect it to be fast. Only one grouping with only a few unique values and many items in each branch sometimes takes upto 30seconds.
Where other cases with many layers of branches and many different values , it only takes 1 second. (The result set is usually around 20 000 rows)
So, my question I guess is simply, what is wrong with my code ? Where am messing up so bad that it would impact performance significantly.
P.S. I'm a relative php novice , so be gentle :)
Sorry, no code comments O_o
$encodable = array();
$rownum = 0;
$branch = null;
$row = null;
$first = true;
$NULL = null;
$result = mysql_query($value,$mysql);
error_log (date("F j, Y, g:i a")."\r\n",3,"debug.log");
if (gettype($result) == "resource")
{
while($obj = mysql_fetch_object($result))
{
$newrow = true;
$branch = &$encodable;
$row = &$NULL;
if (count($branch) > 0)
{
$row = &$branch[count($branch)-1];
}
foreach ($obj as $column => $value)
{
if ($column[0] == '_' && $column[1] == '_')
{
$gname = substr($column,2);
if (isset($row[$gname]) && $row[$gname] == $value)
{
$branch = &$row["b"];
$row = &$NULL;
if (count($branch) > 0)
{
$row = &$branch[count($branch)-1];
}
}
else
{
$branch[] = array();
$row = &$branch[count($branch)-1];
$row[$gname] = $value;
$row["b"] = array();
$branch = &$row["b"];
$row = &$NULL;
if (count($branch) > 0)
{
$row = &$branch[count($branch)-1];
}
}
}
else
{
if ($newrow)
{
$branch[] = array();
$row = &$branch[count($branch)-1];
$newrow = false;
}
$row[$column] = $value;
}
}
$rownum++;
}
}
$encoded = json_encode($encodable);
EDIT:
A sample output - the resulting arrays is converted to json.
This small set is grouped by "av" , b is created by the code for each branche and then contains a list of the [hid , utd] records per AV.
[{"av":"eset nod","b":[{"hid":"3","utd":"1"}]},{"av":"None","b":[{"hid":"2","utd":"0"},{"hid":"4","utd":"0"},{"hid":"5","utd":"0"},{"hid":"1","utd":"0"}]}]
The actual sql result that produced this result is:
+----------+-----+-----+
| __av | hid | utd |
+----------+-----+-----+
| eset nod | 3 | 1 |
| None | 2 | 0 |
| None | 4 | 0 |
| None | 5 | 0 |
| None | 1 | 0 |
+----------+-----+-----+
Turns out its all the calls to count($branch).
Apparently calling a function that doesnt expect a variable by reference like count , With a variable by reference , causes the function to make a Copy of the variable to operate on.
In my case arrays with thousands of elements. Which also explains why its the results with few (but large branches) are the ones that suffer the most.
See this thread:
Why is calling a function (such as strlen, count etc) on a referenced value so slow?