Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Name Number
1 Benjoe 001
2 Benjoe 002
3 Benjoe 001
Given the data, how can I determine that I found duplicate data (Row 1 and 3) using foreach? I have playing with this code right now.
Update: 02/14/2020 - I came up with this algorithm. I've added a flag to determine If I found a duplicate.
$results = [
['name' => 'Benjoe', 'number' => '001'],
['name' => 'Benjoe', 'number' => '002'],
['name' => 'Benjoe', 'number' => '001'],
];
foreach($results as $log) {
if($name == $log->vlg_full_name && $number == $log->vlg_contact_number) {
$isDuplicateNameAndNo = 1;
} else {
$isDuplicateNameAndNo = 0;
break;
}
$name = $log->vlg_full_name;
$number = $log->vlg_contact_number;
}
You can achieve this by a nested loop iterating throug the each element and compating it to the current one.
Try something like that:
<?php
$results = [
['name' => 'Benjoe', 'number' => '001'],
['name' => 'Benjoe', 'number' => '002'],
['name' => 'Benjoe', 'number' => '001'],
];
function compare($log1, $log2, $index1, $index2)
{
return $log1['name'] == $log2['name']
&& $log1['number'] == $log2['number']
&& $index1 != $index2;
}
foreach($results as $index1 => $log1) {
foreach ($results as $index2 => $log2) {
if (compare($log1, $log2, $index1, $index2)) {
echo "Item {$index1} has a duplicate at index {$index2}!<br/>\n";
}
}
}
Here is a link to working example on 3v4l.org
The output for the above will be:
Item 0 has a duplicate at index 2!<br/>
Item 2 has a duplicate at index 0!<br/>
If you don't need to exactly know wich items are duplicate you can simply concatenate the values and put them into an array, and check if the value is already there:
<?php
$results = [
['name' => 'Benjoe', 'number' => '001'],
['name' => 'Benjoe', 'number' => '002'],
['name' => 'Benjoe', 'number' => '001'],
];
$temp = [];
foreach($results as $index => $log) {
$val = $log['name'] . '_' . $log['number'];
if (in_array($val, $temp)) {
echo "Duplicate found at index {$index}<br/>\n";
} else {
$temp[] = $val;
}
}
Output:
Duplicate found at index 2<br/>
Working example on 3v4l.org
If you get your $results from database, another approach would be grouping the query by the requried columns and adding the count(*) field to gind out how many records exists.
Related
I'm trying to mark exam "is_complete" if the "result" reaches 2. I would like to do this when the form is submitted by the user after completing the test and calculating the results. Both variables are in the same table. Is this possible through PHP or do I need to use Java script.
Here is how I've tried to work out the code.
On the model
public function answers()
{
return $this->hasMany('App\ExamResultsAnswers');
}
public function passed()
{
$instance = new ExamResult;
$instance->result < 2;
$var = ExamResult::where('result', '>=', 2)->get();
$var_is_greater_than_two = ($var >= 2 ? true : false);
$condition = new ExamResult;
$condition->is_complete ='1';
if ($this->compare($instance, $condition)) {
return $instance->$column == 1;
}
}
On the controller
public function exam($course_id, Request $request)
{
$course = Course::where('id', $course_id)->firstOrFail();
$answers = [];
$exam_score = 0;
foreach ($request->get('question') as $question_id => $answer_id) {
$question = ExamQuestion::find($question_id);
$correct_answer = ExamOption::where('exam_question_id', $question_id)
->where('id', $answer_id)
->where('is_correct', 1)->count() > 0;
$answers[] = [
'exam_question_id' => $question_id,
'exam_option_id' => $answer_id,
'corect' => $correct_answer
];
if ($correct_answer) {
$exam_score += $question->score;
}
}
$exam_result = ExamResult::create([
'exam_id' => $course->exam->id,
'employee_id' => \Auth::id(),
'result' => $exam_score,
]);
$exam_result->answers()->createMany($answers);
$exam_result->passed();
return redirect()->route('learn.show', [$course, $request])->with('message', 'Test score: ' . $exam_score);
}
The controller is supposed to do the following
Find all the course and the exam that are associated with the course- this works
Then find all the questions and the options for the questions - this works
Then if the user selects the correct answer
then count all correct answers - this works
Then I want to save the
results and mark it complete if the answers are above a 2 correct
answers. - Here the code saves the exam_id, employee_id and result,
but it doesn't make it complete if the result is equal to 2. That is
why I was trying to do this on the model.
Use the following code to mark the Exam as completed:
$exam_result = ExamResult::create([
'exam_id' => $course->exam->id,
'employee_id' => \Auth::id(),
'result' => $exam_score,
]);
$exam_result->answers()->createMany($answers);
if($exam_result->result > 2) {
$exam_result->is_complete = 1;
$exam_result->save();
}
Let me know if i misunderstood the requirement.
Another optimised solution
$exam_result = ExamResult::create([
'exam_id' => $course->exam->id,
'employee_id' => \Auth::id(),
'result' => $exam_score,
'is_complete' => $exam_score > 2
]);
$exam_result->answers()->createMany($answers);
Edit :
i Want a structure like this
'categories' => [
[
'name' => "science" ,
'questions' => [
[
'question' => 'C1_Q2',
'answer' => 'C1_A2',
],
[
'question' => 'C1_Q3',
'answer' => 'C1_A3',
]
]
]
but with help of loop
I am trying to create a questionnaire in which 3 steps need to be done
Create 3 arrays
1.categories - 2d -- like category["science"]["questions"]
2.questions
3.answers
step 1. add 10 questions in question array and add 10 answers in answer arrays
step 2.first 5 question of question array should be inserted to categories["science"]["questions"] and 5 answers to categories["science"]
["answers"]
I created Question and answer array and added 10 , 10 elements in it . but didnt succeed to add its elements as per step2 . I tried few logic
$Category=array();
$Q=array();
$A=array();
for($i=1;$i<=10;$i++)
{
$Q[] = "Question post".$i;
$A[] = "Answer post".$i;
//if($i==5)
//{
// array_push($Category,$Q[i]);
// break;
//} ---logic not working
}
//array first 5 Questions to category array
/*
for($i=1;$i<=5;$i++)
{
//$Category[]=$Q[i];
array_push($Category,$Q[i]);
}
*/ -- not working
print_r($Category);
Any suggestion or help would be appreciated
Try this:
$questions = [];
$answers = [];
for($i=1; $i <= 10; $i++) {
$questions[] = 'Question post' . $i;
$answers[] = 'Answer post' . $i;
}
$categories = ['science', 'something', 'else'];
$result = [];
foreach ($questions as $index => $question) {
if ($index % 5 != 0 || $index == 0) {
$category = current($categories);
} else {
$category = next($categories);
}
$result[$category][] = ['question' => $question, 'answer' => $answers[$index]];
}
var_dump($result);
My question is how can I search an array built this way? Basically there may be a need to repeat the key and this is what I got so far to maybe solve this. If the price is the same for 2 different items I cannot have 2 keys with the same value.
Please feel free to improve on array layout.
$price_list = array(
1 => array("9.99", "EA_WTRESRVD"),
2 => array("9.99", "EA_WTRESRV")
);
Provided there will never be any duplication of the second column, you can do this:
$search = "EA_WTRESRVD"; //value to search for
$price_list = array(
1 => array("9.99", "EA_WTRESRVD"),
2 => array("9.99", "EA_WTRESRV")
);
$array = array_column($price_list, 0, 1);
echo $array[$search];
I would suggest that if you have a unique product code (SKU), you should use this to index your array.
$products = [
'EA_WTRESRVD' => [
'name' => '...',
'price' => 9.99,
// ...
],
'EA_WTRESRV' => [
'name' => '...',
'price' => 9.99,
// ...
],
];
Then you can access the price of any product by it's SKU.
$price = $products['EA_WTRESRV']['price'];
Here's one way:
<?php
$price_list = [ 1 => array("9.99", "EA_WTRESRVD"),
2 => array("9.99", "EA_WTRESRV")];
$search = "EA_WTRESRV";
foreach ($price_list as $arr) {
if (in_array( $search, $arr )) {
echo $search;
}
}
The foreach iterates over the multidimensional array whose elements are each arrays. Each array is inspected by in_array() for the search term.
However, this is not the only way. If you wish to avoid in_array(), you could also code as follows:
<?php
$price_list = [ 1 => array("9.99", "EA_WTRESRVD"),
2 => array("9.99", "EA_WTRESRV")];
$search = "EA_WTRESRV";
$len = strlen($search);
foreach ($price_list as $arr) {
$val = array_values($arr);
foreach($val as $v) {
if ( ( strpos( $v,$search )) !== false) {
if ( strlen($v) == $len) {
echo "$search is in the price list.\n";
}
}
}
}
I created multiple dimensional array and tried to update count value for certain condition as below but not working.
$test[] = [
'firstNm' => 'luke'
,'lastNm' => 'Lee'
,'count' => 10
];
$test[] = [
'firstNm' => 'John'
,'lastNm' => 'Doe'
,'count' => 20
];
foreach ($test as $test01)
{
if ($test01['firstNm'] === 'John'){
$test01['count'] += 70 ;}
}
Looking forward to your help.
Thank you.
Actually you are increasing the value but missing to reasign to the same array. Try this one.
$test[] = [
'firstNm' => 'luke'
,'lastNm' => 'Lee'
,'count' => 10
];
$test[] = [
'firstNm' => 'John'
,'lastNm' => 'Doe'
,'count' => 20
];
foreach ($test as $key => $test01)
{
if ($test01['firstNm'] === 'John'){
$test[$key]['count'] += 70 ;
}
}
print_r($test);
Borrowing from this answer, which cites the PHP manual page for foreach:
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.1
So you could iterate over the array elements by-reference:
foreach ($test as &$test01)
{
if ($test01['firstNm'] === 'John'){
$test01['count'] += 70 ;
}
}
See this illustrated on Teh Playground.
Otherwise you can iterate using the key=>value syntax:
foreach ($test as $index=>$test01)
{
if ($test01['firstNm'] === 'John'){
$test[$index]['count'] += 70 ;
}
}
This question already has answers here:
How do I Sort a Multidimensional Array in PHP [duplicate]
(10 answers)
Closed 8 years ago.
I'm trying to sort the output value that's returned by greatest to least.
Here's an example of the array:
array(
'ACTION' => 'getsupportdepartments',
'RESULT' => 'success',
'TOTALRESULTS' => 2,
'DEPARTMENTS' => array(
'DEPARTMENT' => array(
'ID' => 2,
'NAME' => 'Sales',
'AWAITINGREPLY' => 5,
'OPENTICKETS' => 5
),
'DEPARTMENT1' => array(
'ID' => 1,
'NAME' => 'Support',
'AWAITINGREPLY' => 15,
'OPENTICKETS' => 15
The code I'm using is:
if(!empty($_GET['sort'])) {
$tmpArray = array();
foreach($arr['WHMCSAPI']['DEPARTMENTS'] as $key => $value) {
$tmpArray[$value['AWAITINGREPLY']] = $value;
}
$arr['WHMCSAPI']['DEPARTMENTS'] = $tmpArray;
($_GET['sort'] == 'desc') ? krsort($arr['WHMCSAPI']['DEPARTMENTS']) : ksort($arr['WHMCSAPI']['DEPARTMENTS']);
}
($_GET['sort'] == 'desc') ? krsort($arr['WHMCSAPI']['DEPARTMENTS']) : ksort($arr['WHMCSAPI']['DEPARTMENTS']);
foreach($arr['WHMCSAPI']['DEPARTMENTS'] as $department) {
echo $department['NAME'].' - '.$department['AWAITINGREPLY'].'<br />';
}
echo $exc;
However the order of the output from AWAITINGREPLY is not sorting.
No need to reinvent the wheel, there's already a function called usort:
online demo
function sortDepts(array &$arr,$sort="desc")
{
if($sort=="desc")
usort($arr["DEPARTMENTS"],function($a,$b){
return $b["AWAITINGREPLY"]-$a["AWAITINGREPLY"];
});
else
usort($arr["DEPARTMENTS"],function($a,$b){
return $a["AWAITINGREPLY"]-$b["AWAITINGREPLY"];
});
return $arr;
}
Note that anonymous function works in PHP>=5.3. If you need to support 5<=PHP<5.3, you'll need to declare the function first.
Edit:
For 5 < PHP < 5.3:
online demo
function asc($a,$b)
{
return $a["AWAITINGREPLY"]-$b["AWAITINGREPLY"];
}
function desc($a,$b)
{
return $b["AWAITINGREPLY"]-$a["AWAITINGREPLY"];
}
function sortDepts(array &$arr,$sort="desc")
{
if($sort=="desc")
usort($arr["DEPARTMENTS"],"desc");
else
usort($arr["DEPARTMENTS"],"asc");
return $arr;
}
Edit #2:
In case you still need the key (DEPARTMENT,DEPARTMENT1,etc.), use uasort instead of usort (no other code change is required).