PHP Compare items in an array - php

I have an array in PHP.
My array is the above:
| Student First Name |Student Last Name | Age |Disability|
| Student_First_Name_1 |Student_Last_Name_1 | 30 | 1 |
| Student_First_Name_2 |Student_Last_Name_2 | 28 | 0 |
| Student_First_Name_3 |Student_Last_Name_3 | 21 | 0 |
| Student_First_Name_4 |Student_Last_Name_4 | 20 | 1 |
and I want from this array to compare the entries and make groups and save them to database.
So the student_1 with entry 1 will be grouped with the Student_4 with entry 1 and the Student_2 with the Student_3.
My code is the above:
$count=count($TempSelected);
for($i=1,$j=0;$i<$count;$i++){
if($TempSelected[$j]['disability']==$TempSelected[$i]['disability']){
if( abs($TempSelected[$j]['age']-$TempSelected[$i]['age']) <= 23 ){
$Student1 = $TempSelected[$j]['first_name'].' '.$TempSelected[$j]['last_name'];
$Student2 = $TempSelected[$i]['first_name'].' '.$TempSelected[$i]['last_name'];
unset($TempSelected[$i]);
unset($TempSelected[$j]);
$FirstEntry = $conn->prepare("SELECT id FROM ".$TableName." WHERE Checked = 0 LIMIT 1");
$FirstEntry->execute();
$id = $FirstEntry->fetchColumn();
$data = [
'student_1' => $Student1,
'student_2' => $Student2,
'Checked' => 1,
'id' => $id,
];
$AddStudent = $conn->prepare("UPDATE ".$TableName." SET student_1=:student_1, student_2=:student_2, Checked=:Checked WHERE id=:id");
$AddStudent->execute($data);
}
}
$count=count($TempSelected);
}
But it only make a group and stops.
I want to stops when it make all the groups not only 1.
Can you help me?
I edit my array above and I entered exactly what I have in the array

You need to use nested loops to compare all the pairs of elements. Your code increments $i, but $j is always 0, so you're only comparing with the first student.
for ($i = 0; $i < $count-1; $i++) {
for ($j = $i+1; $j < $count; $j++) {
...
}
}

Related

Group Array items in PHP

I have the above array:
| Student First Name |Student Last Name | Age |Disability|
| Student_First_Name_1 |Student_Last_Name_1 | 30 | 1 |
| Student_First_Name_2 |Student_Last_Name_2 | 28 | 0 |
| Student_First_Name_3 |Student_Last_Name_3 | 21 | 0 |
| Student_First_Name_4 |Student_Last_Name_4 | 20 | 1 |
| Student_First_Name_5 |Student_Last_Name_5 | 22 | 0 |
and I want to grouped the students by age and Disability.
So if my code runs correctly I'll have the above results:
Student_First_Name_1 : Student_First_Name_4
Student_First_Name_3 : Student_First_Name_5
Student_First_Name_2
But instead I have the above:
Student_First_Name_1 : Student_First_Name_4
Student_First_Name_3 : Student_First_Name_5
Student_First_Name_2 : Student_Last_Name_3
Student_First_Name_2 : Student_Last_Name_5
My code is:
$StudentsForSID = $conn->prepare("SELECT * FROM members WHERE sid = :sid AND level = :level");
$StudentsForSID->execute([ 'sid' => $SelectedSID, 'level' => 'LRN_B1' ]);
while($row = $StudentsForSID->fetch(PDO::FETCH_ASSOC)){
$TempSelected[] = $row;
}
$count=count($TempSelected);
for($i=0; $i<$count-1; $i++){
for ($j = $i+1; $j < $count; $j++) {
if($TempSelected[$i]['disability']==$TempSelected[$j]['disability']){
if( abs($TempSelected[$i]['age']-$TempSelected[$j]['age']) <= 23 ){
$Student1 = $TempSelected[$j]['first_name'];
$Student2 = $TempSelected[$i]['first_name'];
print_r($Student1.'-'.$Student2.'<br/>');
}
}
}
}
I don't think I explained very well. So i edit the question.
What I want:
I want to make groups of 2 students with the same value in disability and the age difference between the 2 students to be equal or under 23.
So I have the above array with 5 students. From this array I'll make 3 groups and the groups will be the above (2 groups with 2 students with fulfilled the criteria, and 1 group with one student).
Can you help me?
Thank you
Why don't you use a double group by in your query?
Group by Age , Disability
This will actually group your results into two groups like you wanted so you will save the php sorting and those multiple if and for.

Keep subtracting value in loop getting mysql result php

I have an mysql table named example.
Id | Amount | Left | Filled
1 | 1 | 1 | 0
2 | 4 | 4 | 0
5 | 7 | 7 | 0
I have an variable named $var = 9
Now I have an array named $array with those ids as array([0] => 1, [1] => 2, [2] => 5) Which itself is a mysql result.
How do I make a loop so that ids in array keep subtracting the left and keep filling as per the amount but within the total value of $var so that my end result in table is
Id | Amount | Left | Filled
1 | 1 | 0 | 1
2 | 4 | 0 | 4
5 | 7 | 3 | 4
You can use while loop in order to loop on the ids and reduce the amount in each iteration.
I am not sure how you access your DB so I leave it pseudo.
Consider the following code:
$ids = array(1,2,5);
$value = 9;
function reduceAmount($id, $value) {
$query = mysqli_query($conn, "SELECT * FROM example WHERE Id='$id'");
$row = mysqli_fetch_array($query);
$take = min($row['Left'], $value); // the amount you can take (not more then what left)
$left = $row['Left'] - $take;
$filled = $row['Filled'] + $take;
$conn->query("UPDATE example SET Left='$left', Filled='$filled' WHERE Id='$id'")
return max(0, $value - $take);
}
while ($value > 0 && !empty($ids)) { // check if value still high and the options ids not finish
$id = array_shift($ids); //get first ID
$value = reduceAmount($id, $value);
}
You can check at the end of the loop if value still bigger then 0 - this can happen when no enough "Amount" in ids

Parsing Through a 2D Array in PHP Returning Too Many Columns

I have a sql table in mysql that looks like this:
id | name | age
1 | Jack | 17
2 | John | 18
3 | Luke | 17
4 | Elise | 15
Here is what my code looks like:
$query = "SELECT * FROM table_name;";
$resultStatement = $db->query($query);
$lines = $resultStatement->fetchAll();
for($row = 0; $row < count($lines); $row++)
{
for($col = 0; $col < count($lines[$row]) /*why does this go up to 5?*/; $col++)
{
print $lines[$row][$col] . " ";
}
print "<br>";
}
My question is why does this snippet of code
count($lines[$row])
Go to 5? When I replace that with three my for loops work as intended. Should I give up this approach and go to a foreach loop?

How to handle singularly the last n records of a column in a mysql db using php

I have a database MySQL like this:
------------------------
| id | Name | City |
------------------------
| 1 | John | London |
| 2 | Jim | N.York |
| 3 | Annie | Rome |
By the following query I retrieve the last n data of a specific column:
SELECT id, Name, City FROM mytable ORDER by id DESC limit
0,2
in this case I retrieve the last two records from the columns "id" , "Name" and "City"
How can i associate a specific variable in php to each name of my result?
For example:
$n1 = Annie
$n2 = Jim
So i'll be able to use each single element of the resulting query for my needs in the following part of my php code?
Thanks.
Considering that you have already the results fetched as array you can do this:
for ($i = 1; $i <= count($results); $i++) {
$n{$i} = $results[$i-1];
}
the result in this case will be:
$n1 = array('id' => 3, 'name' => 'Annie'...);
$n2 = array('id' => 2, 'name' => 'Jim');
or you can do:
for ($i = 1; $i <= count($results); $i++) {
$n{$i} = $results[$i-1]['name'];
}
and in this case the result will be:
$n1 = 'Annie';
$n2 = 'Jim';
but the real question is, why not use the results array itself?

Check sentences if have same words

tb_content(left) and tb_word(right) :
===================================== ================================
|id|sentence |sentence_id|content_id| |id|word|sentence_id|content_id|
===================================== ================================
| 1|sentence1| 0 | 1 | | 1| a | 0 | 1 |
| 2|sentence2| 1 | 1 | | 2| b | 0 | 1 |
| 3|sentence5| 0 | 2 | | 3| c | 1 | 1 |
| 4|sentence6| 1 | 2 | | 4| a | 1 | 1 |
| 5|sentence7| 2 | 2 | | 5| e | 1 | 1 |
===================================== | 6| f | 0 | 2 |
| 7| g | 1 | 2 |
| 8| h | 1 | 2 |
| 9| i | 1 | 2 |
|10| f | 2 | 2 |
|11| h | 2 | 2 |
|12| f | 2 | 2 |
================================
I need to check if every sentence consist of words that owned by other sentences in every content_id.
for example :
Check for the content_id = 1 they are sentence1 and sentence2. from tb_word, we can see that sentence1 and sentence2 consist of the same word a. if the number of a in two sentences is >=2, then a will be the result. So if I print the result, it must be :
00Array ( [0] => a [1] => b) 01Array ( [3] => a ) 10Array ( [3] => a )11Array ( [0] => c [1] => a [2] => e) where 00 means sentence_id = 0 and sentence_id = 0
first, I make functionTotal to count how many sentence that owned by every content_id :
$total = array();
$sql = mysql_query('select content_id, count(*) as RowAmount
from tb_content Group By contente_id') or die(mysql_error());
while ($row = mysql_fetch_array($sql)) {
$total[] = $row['RowAmount'];
}
return $total;
From that function I get the value of $total and from that I need to check the similarity of some words (from tb_word) between all the possibilities of 2 sentence
foreach ($total as $content_id => $totals){
for ($x=0; $x <= ($totals-1); $x++) {
for ($y=0; $y <= ($totals-1); $y++) {
$shared = getShared($x, $y);
}
}
the function of getShared is :
function getShared ($x, $y){
$token = array();
$shared = array();
$i = 0;
if ($x == $y) {
$query = mysql_query("SELECT word FROM `tb_word`
WHERE sentence_id ='$x' ");
while ($row = mysql_fetch_array($query)) {
$shared[$i] = $row['word'];
$i++;
}
} else {
$query = mysql_query("SELECT word, count(word) as jml
FROM `tb_word` WHERE sentence_id ='$x'
OR sentence_id ='$y'
GROUP BY word ");
while ($row = mysql_fetch_array($query)) {
$jml = $row['jml'];
$token[$i] = $row['word'];
if ($jml >= 2) {
$shared[$i] = $token[$i];
}
$i++;
}
But the result I get is still wrong. the result still mix between different content_id. the result must be group by content_id also. sorry for my bad english and my bad explanation. cmiiw, please help me.. thank you :)
This one can be actually done by DBMS itself, two steps in one query. First, you make a self join in order to prepare sentence combinations within the same content:
SELECT a.content_id,
a.sentence_id AS sentence_id_1,
b.sentence_id AS sentence_id_2
FROM tb_content AS a
JOIN tb_content AS b
ON ( a.content_id = b.content_id
AND a.sentence_id <= b.sentence_id )
The "<=" will keep same sentence joins, like "1-1" or "2-2", and yet avoid bidirectional repetitions, like "1-2" and "2-1". Next you can join the above result with words and count the number of occurances. Like that:
SELECT s.content_id,
s.sentence_id_1,
s.sentence_id_2,
c.word,
Count(*) AS jml
FROM (SELECT a.content_id,
a.sentence_id AS sentence_id_1,
b.sentence_id AS sentence_id_2
FROM tb_content AS a
JOIN tb_content AS b
ON ( a.content_id = b.content_id
AND a.sentence_id <= b.sentence_id )) AS s
JOIN tb_word AS c
ON ( s.content_id = c.content_id
AND ( c.sentence_id = s.sentence_id_1
OR c.sentence_id = s.sentence_id_2 ) )
GROUP BY s.content_id,
s.sentence_id_1,
s.sentence_id_2,
c.word
HAVING Count(*) >= 2;
The result of the above query will give you the container, sentences 1 and 2, the word, and the number of occurances (which is 2 or more). All you need now is collecting the result into the array which as I see you already know to do.
Let me know, if I missunderstood your goal.
How about simply SELECT content_id, word, COUNT(*) as num_appearing FROM tb_word GROUP BY content_id, word?
EDIT: I see the complexity now: your main issue is that the getShared() function has two sentence IDs passed to it, but no content_id to know which content is being analyzed. You're also assuming that content_id and sentence_id numbers are consecutive and start at zero. My code doesn't assume that, and pulls those IDs directly from the database.
<?php
$rs = mysql_query("SELECT * FROM tb_content");
$content = array();
while ($row = mysql_fetch_assoc($rs)) {
if (!isset($content[$row['content_id']])) $content[$row['content_id']] = array();
$content[$row['content_id']][] = $row['sentence_id'];
}
foreach($content as $content_id => $sentences) {
foreach($sentences as $sentence_id) {
foreach($sentences as $compare) {
$shared = getShared($content_id, $sentence_id, $compare);
}
}
}
function getShared($cid, $s1, $s2) {
$rs = mysql_query("SELECT `word`, COUNT(*) AS 'num' FROM `tb_word` WHERE `content_id`={$cid} AND `sentence_id` IN ({$s1}, {$s2}) GROUP BY `word`");
$out = array();
while ($row = mysql_fetch_assoc($rs)) {
if ($rs['num'] >= 2) $out[$rs['word']] = $rs['num'];
}
return $out;
}

Categories