Any other better logic for this programme - php

Today in an interview i got the following question to solve without using any inbuilt function eg in_array and etc.I am able to solve the programme but they told me is there any better approach and also they told me the total code is only upto 7 lines.So can anyone tell me any better approach than this:-
<?php
$a = array(1,3,5,2,1,5,11,16);
$b = array(1,4,3,11,12,5,7,18);
$final = [];
for($i=0;$i<count($a);$i++){
$flag = 0;
if($i==0){
$final[] = $a[$i];
} else {
for($j=0;$j<count($final);$j++){
if($a[$i] == $final[$j]){
$flag = 1;
}
}
if($flag==0){
$final[] = $a[$i];
}
for($k=0;$k<count($final);$k++){
if($b[$i] == $final[$k]){
$flag = 1;
}
}
if($flag==0){
$final[] = $b[$i];
}
}
}
echo '<pre>';
print_r($final);
the result would be the final array which would contain unique array of both eg
Array ( [0] => 1 [1] => 3 [2] => 4 [3] => 5 [4] => 2 [5] => 11 [6] => 16 [7] => 18 )

Here is how you could do it without using built-in functions: Collect the values as keys (so they are unique), and then put those keys back as values in the final array:
$a = array(1,3,5,2,1,5,11,16);
$b = array(1,4,3,11,12,5,7,18);
foreach($a as $v) $keys[$v] = 1;
foreach($b as $v) $keys[$v] = 1;
foreach($keys as $k => $v) $final[] = $k;
echo '<pre>';
print_r($final);
See it run on eval.in.

Just set the key as the value and they will overwrite. If the arrays are the same length:
foreach($a as $k => $v) {
$final[$v] = $v;
$final[$b[$k]] = $b[$k];
}
If not, then do it for each array:
foreach(array($a, $b) as $c) {
foreach($c as $v) {
$final[$v] = $v;
}
}
The order and keys won't be the same, but that wasn't stated as a requirement.

Related

PHP arrays difference without making use of array_diff

$tag=[25, 26];
$tagarray[]=[25,29,30,44,26];
I need a result of [29,30,44]. Here my main array is tagarray. and tested it with tag array. I need unmatched values from tagarray without any array function like array_diff().I want to compare both arrays and only provide the elements from tagarray which are not present in tag array.
$missings = [];
$matches = false;
for ( $i = 0; $i < count($tagarray); $i++ ) {
$matches = false;
for ($e = 0; $e < count($tag); $e++ ) {
if ( $tagarray[$i] == $tag[$e] ) $matches = true;
}
if(!$matches) array_push($missings,$tagarray[$i]);
}
dd($missings);
You need nested for loops to loop over each element of your array to filter, and for each of these elements, loop on the array containing the filters.
Since you do not want to use any of the array function, you need to use a boolean to check whether or not the index was to be filtered or not and make use of a 3rd array to store the filtered array.
Take a look:
$tag = [25, 26];
$tagarray = [25,29,30,44,26];
$filteredArray = [];
for($i = 0; $i < count($tagarray); ++$i){
$toRemove = false;
for($j = 0; $j < count($tag); ++$j){
if($tagarray[$i] == $tag[$j]){
$toRemove = true;
break;
}
}
if(!$toRemove){
$filteredArray[] = $tagarray[$i];
}
}
var_dump($filteredArray);
Output
array(3) {
[0]=>
int(29)
[1]=>
int(30)
[2]=>
int(44)
}
I would personally not choose this solution and go with Aksen's one, but since you do not want to use any array functions I assume that this is a school assignment and that you have no other choices ;)
If you don't want to use array_diff() then you can use in_array():
$res = [];
foreach($tagarray[0] as $val){
if (!in_array($val,$tag)) $res[] = $val;
}
print_r($res);
Output:
Array
(
[0] => 29
[1] => 30
[2] => 44
)
Demo
If $tagarray has more then 1 element:
$tag=[25, 26];
$tagarray[]=[25,29,30,44,26];
$tagarray[]=[25,22,11,44,26];
$res = [];
foreach($tagarray as $ind=>$tagar){
foreach($tagar as $val){
if (!in_array($val,$tag)) $res[$ind][] = $val;
}
}
Output:
Array
(
[0] => Array
(
[0] => 29
[1] => 30
[2] => 44
)
[1] => Array
(
[0] => 22
[1] => 11
[2] => 44
)
)
Demo
Third Without any inbuilt PHP array function:
$tagar_l = count($tagarray);
$tag_l = count($tag);
$tagar_0_l = count($tagarray[0]);
$res = [];
for($i = 0; $i<$tagar_l; $i++){
$res[] = $tagarray[$i];
for($j = 0; $j<$tagar_0_l; $j++){
for($k = 0; $k<$tag_l; $k++){
if ($tag[$k] === $tagarray[$i][$j]) unset($res[$i][$j]);
}
}
sort($res[$i]);
}
Demo
Via foreach loop:
$res = [];
foreach($tagarray as $ind=>$arr){
$res[] = $arr;
foreach($arr as $ind_a=>$val){
foreach($tag as $comp){
if ($comp === $val) unset($res[$ind][$ind_a]);
}
}
sort($res[$ind]);
}
Demo

Finding unique and duplicate recored in array

Suppose there is array(1,2,2,3,4,4,5)
I want print in this format
A-1
B-2
B-2
A-3
B-4
B-4
A-5
One option would be an iterative approach which in which we iterate over your input array, keeping track of whether the current value differs from the previous value. If it does differ, then we switch the letter prefix from A to B, or vice-versa.
$array = array(1,2,2,3,4,4,5);
$output = array();
$flag = true;
$last_item = NULL;
foreach ($array as $item) {
if ($item != $last_item && $last_item != NULL) {
$flag = !$flag;
}
$prefix = $flag ? "A" : "B";
array_push($output, $prefix."-".$item);
$last_item = $item;
}
print_r($array);
print_r($output);
This prints:
Array
(
[0] => A-1
[1] => B-2
[2] => B-2
[3] => A-3
[4] => B-4
[5] => B-4
[6] => A-5
)
Solution 1.
If it is based on Even/Odd, You can use foreach
foreach($a as $v){
echo ($v % 2) ? 'A-'.$v : 'B-'.$v;echo ' ';
}
https://3v4l.org/XUafK
Solution 2.
Another way, if the same value repetations. You can use array_count_values
$a = array(1,2,2,3,4,4,5);
$b = array_count_values($a);
foreach($a as $v){
echo ($b[$v] > 1) ? 'B-'.$v : 'A-'.$v;
echo '<br/>';
}
Working example :- https://3v4l.org/hopM8
Try This
$arrayst = array(1,2,2,3,4,4,5);
foreach ( $arrayst as $number) {
if ($number % 2) {
echo "A-".$number." ";
}else{
echo "B-".$number." ";
}
}

php how to sort the values in multiple arrays in the order of frequency

I have an array containing multiple arrays like
$A = array();
$A[0] = array("1","2","3","4","5");
$A[1] = array("1","6","7","8");
$A[2] = array("0","1","3");
I want to sort the values in multiple arrays in the order of frequency and put them into another array let's say $B.
The values in $B is "1","1","1","3","3","0","2","4","5","6","7","8".
$A = array();
$A[0] = array("1","2","3","4","5");
$A[1] = array("1","6","7","8");
$A[2] = array("0","1","3");
//Merging above array in to one array
$merged = array_values(call_user_func_array('array_merge', $A));
//Getting occurrence count
$counts = array_count_values($merged);
//Sort by count
arsort($counts);
//Adding to required array
$B = array();
foreach ($counts as $k => $v)
for($i=1;$i<=$v;$i++)
$B[] = $k;
echo "<pre>";
print_r($B);
echo "</pre>";
Result
Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 3
[4] => 3
[5] => 0
[6] => 8
[7] => 7
[8] => 5
[9] => 2
[10] => 4
[11] => 6
)
First merge all arrays
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$resultado = array_merge($array1, $array2);
see -> http://php.net/manual/es/function.array-merge.php
Second sort the big array
arsort($resultado );
see -> http://php.net/manual/es/array.sorting.php
Use a hash table to count the frequency of each number, and then store them in the decreasing order of frequency in array $B, like this:
$hash_table = array();
foreach($A as $array){
foreach($array as $value){
if(empty($hash_table[$value])){
$hash_table[$value] = 1;
}else{
$hash_table[$value] += 1;
}
}
}
arsort($hash_table);
$B = array();
foreach($hash_table as $key => $value){
for($i = 0; $i < $value; ++$i){
$B[] = $key;
}
}
var_dump($B); // to see the contents of array $B
If order of same occurance count items isn't important, you can use:
// Merge all arrays
$counts = array_count_values(call_user_func_array('array_merge', $A));
// Sort by occurance
arsort($counts);
// Add [value] to new array [occurance] times
$B = array();
array_walk($counts, function($occurances, $value) use (&$B){
for($i=0;$i<$occurances;$i++) $B[] = $value;
});
echo implode(',', $B);
Output
1,1,1,3,3,0,8,7,5,2,4,6
Array print in order of count and index:
$temp = array();
foreach($A as $b){
foreach($b as $c){
if(isset($tmep[$c])){
$tmep[$c]++;
}else{
$tmep[$c] = 1;
}
}
}
function SortArrayByKeyThanValue (&$pArray, $pSortMethodForKey = SORT_ASC, $pSortMethodForValue = SORT_DESC){
# check user input: sorting is not necessary
if (count($pArray) < 2)
return;
# define $k and $v as array_multisort() needs real variables, as user input is put by reference
$k = array_keys ($pArray);
$v = array_values($pArray);
array_multisort(
$v, $pSortMethodForValue,
$k, $pSortMethodForKey
);
$pArray = array_combine($k, $v);
}
SortArrayByKeyThanValue($tmep);
$B = array();
array_walk($tmep, function($occurances, $value) use (&$B){
for($i=0;$i<$occurances;$i++) $B[] = $value;
});
echo implode(',', $B);

Count the number of numeric keys in an array

I'm using PHP 5.6, and I have the following array:
Array (
[0] => Array (
[id] => 1
[name] => James
)
[1] => Array (
[id] => 2
[name] => Tim
[children] => Array (
[0] => Array (
[id] => 4
[name] => Sam
)
[1] => Array (
[id] => 5
[name] => Florence
)
)
)
[2] => Array (
[id] => 3
[name] => Stephen
)
)
I'm trying to find a neat and fast way to count the number of people, which is the same as counting the number of numeric keys, which should be 5.
echo count($myarray); // 3 (only first level)
echo count($myarray, COUNT_RECURSIVE); // 16 (every key/value)
Is there a good way to do this with built-in PHP functions, or do I need to traverse the whole multidimensional array and count them manually..?
EDIT My array could end up being 1,000+ people (or more), with many many levels (an unknown number of levels).
It is important to note that, even if there were a PHP built-in (such as count($myarray, COUNT_RECURSIVE_NUMERIC);) internally, it would still be traversing the whole array, recursively. If you are worried about Out Of Memory errors, try pass-by-reference, which will not copy the array or the array items:
define('COUNT_RECURSIVE', 1);
function count_numeric_keys(&$array, $flags = 0) {
$count = 0;
foreach ($array as $key => $value) {
$count += (int) (is_numeric($key));
if ($flags & COUNT_RECURSIVE && is_array($value)) {
$count += count_numeric_keys($value, $flags);
}
}
return (int) $count;
}
$count = count_numeric_keys($array, COUNT_RECURSIVE);
Mayhaps?
Comparison with non-pass-by-reference, type-hint, and small benchmark:
define('COUNT_RECURSIVE', 1);
function count_numeric_keys(Array &$array, $flags = 0) {
$count = 0;
foreach ($array as $key => $value) {
$count += (int) (is_numeric($key));
if ($flags & COUNT_RECURSIVE && is_array($value)) {
$count += count_numeric_keys($value, $flags);
}
}
return (int) $count;
}
function count_numeric_keys_np(Array $array, $flags = 0) {
$count = 0;
foreach ($array as $key => $value) {
$count += (int) (is_numeric($key));
if ($flags & COUNT_RECURSIVE && is_array($value)) {
$count += count_numeric_keys_np($value, $flags);
}
}
return (int) $count;
}
$tpl_array = array(
1=>"one",
"two"=>"two",
3=>array(
1=>1,
"two"=>2
)
);
// Fill the array with both numeric and non-numeric
$array = array();
for($i = 1000; $i > 0; $i--) {
$array[] = $tpl_array;
}
for($i = 1000; $i > 0; $i--) {
$array["not a number $i"] = $tpl_array;
}
echo "Pre Memory: ".memory_get_usage(TRUE).PHP_EOL;
echo "Count: ".count_numeric_keys($array, COUNT_RECURSIVE).PHP_EOL;
echo "Reference Memory: ".memory_get_usage(TRUE)." current, ".memory_get_peak_usage(TRUE)." peak.\n";
count_numeric_keys_np($array, COUNT_RECURSIVE);
echo "No-Reference Memory: ".memory_get_usage(TRUE)." current, ".memory_get_peak_usage(TRUE)." peak.\n";
View it on IDEONE here.
ODDLY, having a reference on $value, like foreach($array as $key => &value) {} actually increased memory usage. Bizarre...
I just created this recursive function to do this for ya :P
function countNumericKeys($array)
{
$count = 0;
foreach ($array as $key => $value)
{
if (is_numeric($key))
{
$count ++;
}
if (is_array($value))
{
$count += countNumericKeys($value);
}
}
return $count;
}
// Test it!
$array = [
1=>"one",
"two"=>"two",
3=>[
1=>1,
"two"=>2
]
];
print countNumericKeys($array); // Output: 3, correct (in this case at least)!
Shortened the code so it uses ternary operators instead of the ifs that it was :P
function simpleCountNumericKeys($array)
{
$count = 0;
foreach ($array as $key => $value)
{
$count += is_numeric($key) ? 1 : 0;
$count += is_array($value) ? simpleCountNumericKeys($value) : 0;
}
return $count;
}
TEST USING array_keys -- only gets the top level keys of the array
function countArrayKeysNumeric($array)
{
$count = 0;
$keys = array_keys($array);
foreach ($keys as $key) $count += is_numeric($key) ? 1 :0;
return $count;
}
$array = [
1=>"one",
"two"=>"two",
3=>[
1=>1,
"two"=>2
]
];
print countArrayKeysNumeric($array);
Prints 2... :(

Merge 2 arrays by appending values

I have 2 arrays
$a = array('v1'=>1,'v2'=>2,'v3'=>3,'v4'=>4);
$b = array('v1'=>1,'v2'=>2,'v3'=>3,'v4'=>5);
How do I merge them to a single array like this :
Array
(
[v1] => 1
[v2] => 2
[v3] => 3
[v4] => Array
(
[0] => 4
[1] => 5
)
)
I have tried using array_merge & array_merge_recursive.
You can use this code:
$a = array('v1'=>1,'v2'=>2,'v3'=>3,'v4'=>4);
$b = array('v1'=>1,'v2'=>2,'v3'=>3,'v4'=>5);
$c = array();
foreach($a as $m => $n) {
if (($b[$m] != $n))
$c[$m] = array($n, $b[$m]);
else
$c[$m] = $n;
}
$result = array_intersect_assoc($a, $b);
foreach (array_diff_assoc($a, $b) as $k => $v)
$result[$k] = array($v, $b[$k]);
Update:
anubhava's solution is good. It can be simplified like this:
$c = array();
foreach($a as $k => $v)
$c[$k] = $b[$k] == $v ? $v : array($v, $b[$k]);
$a = array('v1'=>1,'v2'=>2,'v3'=>3,'v4'=>4);
$b = array('v1'=>1,'v2'=>2,'v3'=>3,'v4'=>5);
$results = array();
foreach ($a as $key=>$elem) {
$results[$key][] = $elem;
if (!in_array($b[$key], $results[$key])) {
$results[$key][] = $b[$key];
}
}

Categories