PHP unshif and push value based on current array keys - php

I have a quiz where you can use text field or radio buttons for the answers. The answers are stored in a database. None of the answers are required so people can skip questions.
Each entry is stored in a row:
Array
(
[0] => Array
(
[0] => Dave
[1] => ok
[2] => Manchester
[3] => No
)
[1] => Array
(
[0] => James
[1] => Happy
[2] => London
[3] => Yes
)
[2] => Array
(
[0] => Victoia
[2] => Leeds
)
)
Currently the question number is represented by the key. So Victoria hasn't answered question 1 or 3. My aim is to add the unanswered into the array witht the correct key value being null.
Here is my code so far but I'm struggling to get the array key position correct:
$answersArr = (array) $answers;
$row = array();
$items = array();
$numberOfQuesitons = count($headers);
foreach ($answersArr as $key=>$result) {
$answer = json_decode(stripslashes($result->answers));
$row[$key] = (array) $answer;
$single = count($row[$key]);
$currentKey = key($row[$key]);
for ($i = $single ; $i < $numberOfQuesitons; $i++) {
if ($numberOfQuesitons - $i > 0) {
if ($currentKey > 0) {
array_unshift($row[$key], null);
} else {
array_push($row[$key], null);
}
}
}
}
print_r($row);
The out put I get:
Array
(
[0] => Array
(
[0] => Admin
[1] => ok
[2] => Manchester
[3] => No
)
[1] => Array
(
[0] => Rod
[1] => Happy
[2] => London
[3] => Yes
)
[2] => Array
(
[0] => Rozi
[2] => Leeds
[3] =>
[4] =>
)
)
The last row in the array needs to look like this:
[2] => Array
(
[0] => Victoia
[1] =>
[2] => Somewhere
[3] =>
)
A little stuck here any help would be much appreciated.
Thanks

Let me say that I read through your code and have to make two assumptions: $numberOfQuesitons = 4 and $single = 2 in the case of Victoia.
Assumption is based on the fact that the name of a person is included in the result arrays and otherwise could not be derived.
So in your code at the iteration of Victoia we will have the following array to work with:
$row[$key] = [
0 => 'Victoia',
2 => 'Leeds',
];
Then at the inner for loop the following will happen (as noted in comments):
for ($i = $single; $i < $numberOfQuesitons; $i++) {
// 4 - 2 = 2, 2 > 0 = true <-- first iteration
// 4 - 3 = 1, 1 > 0 = true <-- second (and final) iteration
if ($numberOfQuesitons - $i > 0) {
// $currentKey doesn't change in this process
// and since the key is taken from the array
// $row[$key] points to, the key function will return 0 each iteration.
if ($currentKey > 0) {
// Also note that unshift will only add elements to the front of the array.
array_unshift($row[$key], null);
} else {
// Hence we drop down in this branch of the if statemtent
// as 0 > 0 evaluates to false each evaluation.
// So we start with [0] => Rozi || Victoia
// [2] => Leeds || Somewhere
// Push null thus: [3] => null
// Push null thus: [4] => null
// Hence our final result.
// Also note that push only 'pushes' elements at the end of the array.
array_push($row[$key], null);
}
}
}
To solve this we could change the logic a little bit, but personally I would modify the nested loop to the following (or something similar):
$answersArr = (array) $answers;
$row = array();
$numberOfQuesitons = count($headers);
foreach ($answersArr as $key => $result) {
$answer = json_decode(stripslashes($result->answers));
$row[$key] = (array) $answer;
// We simply create a range from 0 up to the last question number.
$all = range(0, $numberOfQuesitons - 1);
// Taking the difference between all questions and the answered
// ones will give us the missing ones.
$unAnsweredQs = array_diff($all, array_keys($row[$key]));
// Add those missing questions to the array.
foreach ($unAnsweredQs as $unAnswered) {
// Or maybe a more appropriate default.
$row[$key][$unAnswered] = null;
}
// Sort the keys, such that we respect the wanted order
// Name (key 0), Q1, Q2, ..., QN
ksort($row[$key]);
}
print_r($row);

Related

How can I select 2 items each in an array making sure every set is outputed

Lets say I have an array of numbers: [1,2,3].
How can I loop through this array to create an array of possible permutations.
I'm expecting outputs like:
[1,2], [1,3], [2,1], [2,3], [3,1], [3,2].
Simple nested loops required for the same input array
Do the following:
$input = array(1,2,3);
$output = array();
// to get all possible permutations
// for first value in the permutation, loop over all array values
foreach ($input as $value1) {
// for second value in the permutation, loop again similarly
foreach ($input as $value2) {
if ($value1 !== $value2) // dont consider same values
$output[] = array($value1, $value2);
}
}
If i understand the question correctly, you want to have an array containing X amount of integers and get every possible combination of two distinct integers from that array?
This can be done with two for loops, one to loop through each of your array's elements, and another that combines that element with every other element.
for(int $x = 0; $x < count($arr1); $x++) {
for(int $y = 0; $y < count($arr1); $y++) {
if ($x == $y || $arr1[$x] == $arr1[$y]) {
continue;
} else {
array_push($output, [$arr1[$x], $arr1[$y]]);
}
}
}
Looking at your example I assumed you don't want repeating numbers. So I did a loop with an inner loop and compared the numbers before adding to the print Array! My first stackoverflow submissions so I'd love some feedback!
$arrayToParse = [1, 2, 3];
$arrayToPrint = [];
foreach($arrayToParse as $num1){
foreach($arrayToParse as $num2){
if($num1 != $num2){
array_push($arrayToPrint, [$num1, $num2]);
}
}
}
print_r($arrayToPrint);
// OUTPUT
Array
(
[0] => Array
(
[0] => 1
[1] => 2
)
[1] => Array
(
[0] => 1
[1] => 3
)
[2] => Array
(
[0] => 2
[1] => 1
)
[3] => Array
(
[0] => 2
[1] => 3
)
[4] => Array
(
[0] => 3
[1] => 1
)
[5] => Array
(
[0] => 3
[1] => 2
)
)

Read the categories and subcategories in csv format and prepare multidimensional array

In the PHP, I need to convert the below image CSV file in this array format:
This code for creating categories and subcategories. If client will add the extra categories and subcategories its need to work as per that. So I need the dynamic one.
Array Format :
Array
(
[0] => Cateory1
[Cateory1] => Array
(
[0] => SubCategory11
[1] => SubCategory12
[2] => SubCategory13
[3] => SubCategory14
)
[1] => Cateory2
[Cateory2] => Array
(
[0] => SubCategory21
[1] => SubCategory22
[2] => SubCategory23
[SubCategory23] => Array
(
[0] => SubCategory221
[1] => SubCategory222
)
[3] => SubCategory24
)
[2] => Cateory3
[Cateory3] => Array
(
[0] => SubCategory31
[1] => SubCategory32
[2] => SubCategory33
)
[3] => Cateory4
[Cateory4] => Array
(
[0] => SubCategory41
[SubCategory41] => Array
(
[0] => SubCategory411
[SubCategory411] => Array
(
[0] => SubCategory4111
[SubCategory4111] => Array
(
[0] => SubCategory41111
)
)
)
)
)
Kindly help me to achieve this one.
Thanks.
Although i agree with Pitchinnate, I had some spare time and I hate parsing that sort of csv rubbish, so I thought I give it a try. Here is a piece of code that might get you going. I did not test or optimize anything, so if this doesn't work as expected, it might still point you in the right direction.
// I assume, $imput is a twodimensional array containing the csv data
// the multi dimensional result array
$result = array();
// accumulated categories of current-1 line
$lastCat = array();
foreach($input as $line) {
// accumulated categories of current line
$cat = array();
//First we create an array in $cat that contains the full "breadcrumbs" per line e.g.
// ['category1', 'SubCategory11', 'SubCategory114', ...]
$marker = PHP_INT_MAX;
for ($i=0; $i<count($line); $i++) {
if ($marker < $i) {
$cat[$i] = '';
} else if ($line[$i] != '') {
$cat[$i] = $line[$i];
$marker = $i;
}
}
// then using these category breadcrumbs, we create the result arrays
// you could do this using recursion if you want
$tmp = $result;
for ($i=0; $i<count($cat); $i++) {
// if we haven't seen this category yet, create it
// a bit bulky, but necessary as you want the categories with numeric indices as well
if (!isset($lastCat[$i]) || $cat[$i] != $lastCat[]) {
$tmp[] = $cat[$i];
// Check if there are still subcategories left in this line...
if (!empty($cat[$i+1])) {
//... and if so, create the category named index if not already existing
if (!array_key_exists($cat[$i], $tmp)) {
$tmp[$cat[$i]] = array();
}
$tmp = $tmp[$cat[$i]];
} else {
// ... and if not, we are finished with this line
break;
}
}
}
$lastCat = $cat;
}

How to make an array using other 2 array

$champions array =
Array (
[0] => Shen
[1] => Graves
[2] => Lux
[3] => Tristana
[4] => Janna
[5] => Lissandra
[6] => RekSai
[7] => Anivia
[8] => Lucian
[9] => Alistar )
This array has always 10 values.
$fbps array =
Array (
[0] => RekSai
[1] => Alistar
[2] => Lucian )
This array has always 1-5 values.
What i want to make
Array (
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
[5] => 0
[6] => 1
[7] => 0
[8] => 1
[9] => 1 )
My english is bad to explain this, i hope arrays are enough to tell. Sorry for bad title and explanation.
Edit: Ill try to explain it more. For example Shen's key is 0 in first array. $fbps array doesnt have a value named "Shen" so in third array 0 => 0. Lucian's key is 8 in first array. fbps have a value named Lucian. So third arrays 8th key has value "1"
$cArr = array('Shen','Graves','Lux','Tristana','Janna','Lissandra','RekSai','Anivia','Lucian','Alistar');
$fbps = array('RekSai','Anivia','Lucian');
foreach ($cArr as $key=>$value) {
if(array_search($value, $fbps) !== false) {
$cArr[$key] = 1;
} else {
$cArr[$key] = 0;
}
}
var_dump($cArr);
Or a more compact version:
$cArr = array('Shen','Graves','Lux','Tristana','Janna','Lissandra','RekSai','Anivia','Lucian','Alistar');
$fbps = array('RekSai','Anivia','Lucian');
foreach ($cArr as $key=>$value) {
$cArr[$key] = (array_search($value, $fbps) !== false) ? 1 : 0;
}
var_dump($cArr);
EDIT:
added in the !== false conditional as matches found in position 0 of the $fbps array incorrectly evaluated to false because 0 also = false in PHP land...
EDIT 2:
This function has O(N) complexity, meaning it'll grow linearly and in direct proportion to the size of the input data set.
Does the resulting array just have a value of 1 for every element of $fbps that appears in $champions? If so, something like this should do it;
$champions = ['Shen', 'Graves', 'Alister', '...'];
$fbps = ['Shen', 'Alister', '...'];
$result = array_map(function($value) use ($fbps) {
return (int)in_array($value, $fbps);
}, $champions);
I know you've already accepted an answer but here is the most efficient solution:
<?php
// Your arrays
$champions = array('Shen','Graves','Lux','Tristana','Janna','Lissandra','RekSai','Anivia','Lucian','Alistar');
$fbps = array('RekSai','Alistar','Lucian');
// New array which will store the difference
$champ_compare = array();
// Flip the array so that it is associative and uses the names as keys
// http://php.net/manual/en/function.array-flip.php
$fbps = array_flip($fbps);
// Loop all champions and use $v as reference
foreach($champions as &$v)
{
// Check for the existent of $v in the associative $fbps array
// This is leaps and bounds faster than using in_array()
// Especially if you are running this many times with an unknown number of array elements
$champ_compare[] = (int)isset($fbps[$v]);
}
unset($v);
// Flip it back if you need to
$fbps = array_flip($fbps);
print_r($champ_compare);
If you just want the most compact code and do not care about performance then you can try this:
<?php
// Your arrays
$champions = array('Shen','Graves','Lux','Tristana','Janna','Lissandra','RekSai','Anivia','Lucian','Alistar');
$fbps = array('RekSai','Alistar','Lucian');
// New array which will store the difference
$champ_compare = array();
// Loop all champions and use $v as reference
foreach($champions as &$v)
{
// Check if the current champion exists in $fbps
$champ_compare[] = (int)in_array($v, $fbps);
}
unset($v);
print_r($champ_compare);
Not as detailed as Garry's answer, but is based on your existing arrays.
$res = array()
foreach($champions as $key => $val) {
$res[$key] = (in_array($val, $fbps)) ? 1 : 0;
}
var_dump($res)
Edit: I've switched the array_key_exists to in_array.
<?php
$champions = array('Shen', 'Graves', 'Lux', 'Tristana', 'Janna', 'Lissandra', 'RekSai', 'Anivia', 'Lucian', 'Alistar');
$fbps = array('RekSai', 'Alistar', 'Lucian');
$res = array();
foreach($champions as $key => $val) {
$res[$key] = (in_array($val, $fbps)) ? 1 : 0;
}
var_dump($res);

merge array items specific array items

I got this array:
array (
0 => 'K.',
1 => 'Vrachtschip',
2 => 'L.',
3 => 'Gevechtsschip',
4 => 'Z.',
5 => 'Gevechtsschip',
6 => 'Kruiser',
7 => 'Slagschip',
8 => 'Bommenwerper',
9 => 'Vernietiger',
10 => 'Interceptor.',
)
of can I merge the items [0] with [1], because K. vrachtschip must be together.
same ass [2] and [3]; and [4] with [5]. if there is 1 letter and then a dot (k.) it must be merged with the following array item.
Anyone that can help me :)?
How about:
$arr = array (
'K.',
'Vrachtschip',
'L.',
'Gevechtsschip',
'Z.',
'Gevechtsschip',
'Kruiser',
'Slagschip',
'Bommenwerper',
'Vernietiger',
'Interceptor',
'B.',
);
$concat = '';
$result = array();
foreach ($arr as $elem) {
if (preg_match('/^[A-Z]\.$/', $elem)) {
$concat = $elem;
continue;
}
$result[] = $concat.$elem;
$concat = '';
}
if ($concat) $result[] = $concat;
print_r($result);
output:
Array
(
[0] => K.Vrachtschip
[1] => L.Gevechtsschip
[2] => Z.Gevechtsschip
[3] => Kruiser
[4] => Slagschip
[5] => Bommenwerper
[6] => Vernietiger
[7] => Interceptor
[8] => B.
)
Try to use a regular expression to test all entries of your array.
If an occurence is founded, concat the value of your entrie with the next.
I would try something like this:
for($idx=0, $max = count($array_in); $idx < $max; $idx++)
{
if(preg_match('/^[a-z]\.$/i', $array_in[$idx]))
{
$array_out[] = $array_in[$idx].$array_in[$idx+1];
$idx++;
}
else
{
$array_out[] = $array_in[$idx];
}
}
I'd probably do the following (pseudo code):
Create empty array for result
Iterate the original array
For each value: does it match /^[a-z]\.$/i?
If yes, see if original array contains a next element?
If yes, concatenate the two items and add to resulting array, skip next item in loop
If no (pt. 4 or 5) add directly to resulting array.

Breaking an array into groups based on values

Using PHP, I'm trying to break an array up into multiple arrays based on groups of values. The groups are based on the values being between 1 and 5. But here's the hard part...
I need to loop through the array and put the first set of values that are between 1 and 5 in their own array, then the next set of values that are between 1 and 5 in their own array, and so on.
But each group WON'T always include 1,2,3,4,5. Some groups could be random.
Examples:
1,1,2,2,3,4,5 - this would be a group
1,2,3,4,4,4 - this would be a group
1,2,3,3,5 - this would be a group
2,2,3,3,5 - this would be a group
So I can't just test for specific numbers.
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 1
[6] => 2
[7] => 3
[8] => 4
[9] => 4
[10] => 1
[11] => 1
[12] => 3
[13] => 4
[14] => 5
)
Any Ideas?
I would just check if the current value is larger than the previous value, and if yes, begin a new group.
$groups = array();
$groupcount = 1;
foreach( $array as $key=>$value )
{
if( $key > 0 ) // there's no "previous value" for the first entry
{
if( $array[$key] < $array[$key-1] )
{
$groupcount = $groupcount + 1;
}
}
$group[groupcount][] = $value;
}
Is this what you are looking for?
$groups = array();
$cur = array();
$prev = 0;
foreach ($numbers as $number)
{
if ($number < $prev)
{
$groups[] = $cur;
$cur = array();
}
$cur[] = $number;
$prev = $number;
}
if ($cur) $groups[] = $cur;
Untested. (Edit: corrected some obvious mistakes.)

Categories