How to make an array using other 2 array - php

$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);

Related

PHP unshif and push value based on current array keys

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);

Unset Element from Array IF

I get some data from the database, which is saved in "$Data". $Data looks like this:
[Data] => Array
(
[0] => Array
(
[PrinterID] => 3
[PrinterName] => PRT03_EDV
[isDefaultPrinter] => 1
[isMapped] => 0
)
[1] => Array
(
[PrinterID] => 1
[PrinterName] => PRT01_Zentral
[isDefaultPrinter] => 0
[isMapped] => 1
)
[2] => Array
(
[PrinterID] => 2
[PrinterName] => PRT02_BH
[isDefaultPrinter] => 0
[isMapped] => 0
)
I need to verify, that there is no array in $Data, where "isDefaultPrinter == True" and "isMapped == False". Programatically:
if ( $Data["isDefaultPrinter"] == true and $Data["isMapped"] == false ) {
// Remove from Array
}
I did start to code this on my own based on this and my result was a terrible looking nested loop, which did not work :-(
I am a beginner and I wanted to ask, if there is an nice and easy way to do this?
Thank you
Here's a version using array_filter, which is sort of built for this. See http://php.net/manual/en/function.array-filter.php
$valid = array_filter($Data, function($var) {
return !($var['isDefaultPrinter'] && !$var['isMapped']);
});
Use foreach to loop over the data array:
foreach ($Data['Data'] as $entry) {
// Examine every entry
if ($entry['isDefaultPrinter'] && !$entry['isMapped']) {
// $entry does not meet criteria
}
}
You can write a function that verifies that every entry meets your criteria:
function validateData($Data) {
foreach ($Data['Data'] as $entry) {
// Examine every entry
if ($entry['isDefaultPrinter'] && !$entry['isMapped']) {
// $entry does not meet criteria
return false;
}
}
// Everything is OK
return true;
}
var_dump(validateData($Data));
You can use unset to remove the row of the array that doesn't fit your "keep" criteria. You need to know the array key to remove it tidily; this foreach with the $key value as well:
foreach ($var['Data'] as $key => $entry) {
// Examine every entry
if ($entry['isDefaultPrinter'] && !$entry['isMapped']) {
// $entry does not meet criteria
unset($var['Data'][$key]);
}
}
print_r($var); //output remaining values.
Once completed - and if you wish - you can then reindex the [outer] array using array_values():
$var['Data'] = array_values($var['Data']);

How to merge two arrays and sum the values of duplicate keys? [duplicate]

This question already has answers here:
How to merge two arrays by summing the merged values [duplicate]
(3 answers)
Closed 5 months ago.
I would like to merge array by conditions. If array keys match then add the values, if not then retain the value.
Here are my arrays:
Array1
(
[1] => 199
[3] => 1306
[5] => 199
)
Array2
(
[3] => 199
[4] => 199
)
My desired result is:
Result
(
[1] => 199
[3] => 1505
[4] => 199
[5] => 199
)
I used if-else conditions, but it's repeating the value which is already matched.
Here is my coding attempt:
$all=array();
foreach($sall as $sskey => $ssvalue){
foreach($upgradesall as $uukey => $uuvalue){
//$sskey==$uukey?$all[] = array("id"=>$sskey, "amount"=>$ssvalue+$uuvalue):($sskey!=$uukey? $all[] = array("id"=>$sskey, "amount"=>$ssvalue):($uukey!=$sskey?$all[] = array("id"=>$uukey, "amount"=>$uuvalue):''));
if($sskey===$uukey){
$all[] = array("id"=>$sskey, "amount"=>$ssvalue+$uuvalue);
}elseif($sskey!=$uukey){
$all[] = array("id"=>$sskey, "amount"=>$ssvalue);
}elseif($uukey!=$sskey){
$all[] = array("id"=>$uukey, "amount"=>$uuvalue);
}
}
}
I think the problem is simpler than it looks. You really only need a conditional to preclude undefined offset notices. Just iterate all keys and values in both arrays and add the values to the corresponding key in the merged array.
foreach ([$a1, $a2] as $a) { // iterate both arrays
foreach ($a as $key => $value) { // iterate all keys+values
$merged[$key] = $value + ($merged[$key] ?? 0); // merge and add
}
}
Really, the line that actually does the addition ($merged[$key] = $value + ($merged[$key] ?? 0);) could be reduced to $merged[$key] += $value;. That would still work, but it would produce a bunch of undefined offset notices. So instead we can set the key equal to the value plus either the previous value (if it exists) or zero.
If you're still using PHP 5, you can use a ternary instead of the null coalescing operator (??), like this:
$merged[$key] = $value + (isset($merged[$key]) ? $merged[$key] : 0);
The output won't be in the same order shown in your desired result, but you can use ksort($merged); to accomplish that
First you can merge the arrays by merging all values in the same key:
$allKeys = array_unique(array_merge(array_keys($arr1),array_keys($arr2)));
$result = [];
foreach ($allKeys as $key) {
$result[$key] = [];
if (array_key_exists($key,$arr1)) {
$result[$key][] = $arr1[$key];
}
if (array_key_exists($key,$arr2)) {
$result[$key][] = $arr2[$key];
}
}
This will result in:
Array
(
[1] => Array
(
[0] => 199
)
[3] => Array
(
[0] => 1306
[1] => 199
)
[5] => Array
(
[0] => 199
)
[4] => Array
(
[0] => 199
)
)
Then you can map them according to your conditions:
$endResult = array_map('array_sum',$result);
Result:
Array
(
[1] => 199
[3] => 1505
[5] => 199
[4] => 199
)
If you want the keys to be sorted you can run them through a ksort as well
Check the code:
http://sandbox.onlinephpfunctions.com/code/3eb23310f0fd8de8174a5caf8b2b91d4b7562b6b
You could achieve that by
$all = array_merge($arr1,$arr2); // existing elements in arr1 are replaced by arr2 else merge into new array_merge
//then add replaced elememnts value
foreach($arr1 as $k=>$v)
{
if(array_key_exists($k,$all))
{
$all[$k] = $all[$k] + $v;
}
}

Find in array and get count of each string

I am fetching some data from the db and then push them to an array. I need to find the count of some strings and print out the result (count) in an efficient way:
Array
(
[0] => q1-1,q2-2,q3-2,q4-1,q5-2,q6-3,q7-1,q8-4,
[1] => q1-1,q2-2,q3-1,q4-3,q5-3,q6-3,q7-2,q8-1,
[2] => q1-1,q2-1,q3-1,q4-1,q5-1,q6-2,q7-2,q8-2,
[3] => q1-3,q2-1,q3-1,q4-1,q5-2,q6-3,q7-1,q8-1,
[4] => q1-2,q2-2,q3-3,q4-1,q5-3,q6-3,q7-1,q8-1,
[5] => q1-1,q2-2,q3-3,q4-1,q5-2,q6-3,q7-1,q8-1,
[6] => q1-3,q2-1,q3-1,q4-3,q5-2,q6-3,q7-2,q8-4,
[7] => q1-2,q2-2,q3-3,q4-1,q5-2,q6-5,q7-1,q8-1,
[8] => q1-1,q2-1,q3-2,q4-3,q5-3,q6-5,q7-1,q8-1,
[9] => q1-2,q2-1,q3-1,q4-1,q5-3,q6-3,q7-1,q8-1,
[10] => q1-3,q2-2,q3-3,q4-3,q5-4,q6-3,q7-1,q8-1,
...
)
Sample data is above.
I need to know how many occurences of q1-1, q1-2 ... q8-4 is in the array and print out readable version. Ex. The are 23: q1-1, 412: q1-2 and so on.
I was going to create an array of each string that needs to be searched that iterate through the array. For every result increment the resultVariable for that string but I'm not sure if that's the best way.
Suggestions?
Pretty simple, loop on your array, create sub arrays, and create a counter array:
$counts = array () ;
foreach ( $your_array as $row ) {
$sub = explode(',', $row);
foreach ( $sub as $subval ) {
if ( array_key_exists ( $subval, $counts ) ) {
$counts[$subval] ++ ;
} else {
$counts[$subval] = 1 ;
}
}
}
Here is $counts:
Array (
'q1-1' => 23,
'q1-2' => 9,
// and so on....
);
Try:
$arr = array(...); //your array
$count = array();
foreach($arr as $v) {
$substr = explode(',', $v);
foreach($substr as $m) {
if(strstr($v, $m) !== FALSE)
$count[$m]++;
}
}
Printing the counts,
foreach($count as $k => $v)
echo "Count for '$k': ". $v;

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.

Categories