$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
Related
This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 3 years ago.
I am trying to create an algorithm that shows each step of bubble sort, sorting one number at a time. I was was able to sort the number at the first index, but I need to figure out how to sort all the numbers.
$x = array (9,7,5,3,0);
$count = count($x);
for($i = 0; $i < $count-1; $i++ ) {
$temp = $x[$i+1];
$x[$i+1] = $x[$i];
$x[$i] = $temp;
echo '<pre>';
print_r($x);
}
My current output is:
Array
(
[0] => 7
[1] => 9
[2] => 5
[3] => 3
[4] => 0
)
Array
(
[0] => 7
[1] => 5
[2] => 9
[3] => 3
[4] => 0
)
Array
(
[0] => 7
[1] => 5
[2] => 3
[3] => 9
[4] => 0
)
Array
(
[0] => 7
[1] => 5
[2] => 3
[3] => 0
[4] => 9
)
From here I need to continue sorting the remaining numbers. For 7, the output should be
57390
53790
53970
53907
and then for 3
35079
30579
30759
30795
and then for 0, it should be same for all 4 lines like
03570
03579
03579
03579
[The assigned problem.][1]
Two issues:
You should only swap values when they are not in the right order
You need an outer loop to repeat this inner loop, similar to a proper bubble sort algorithm.
Your code can be modified like below so it generates the required output:
$x = array (9,7,5,3,0);
$count = count($x) - 1;
for($times = 0; $times < $count; $times++) {
for($i = 0; $i < $count; $i++ ) {
$temp = $x[$i+1];
if ($temp < $x[$i]) {
$x[$i+1] = $x[$i];
$x[$i] = $temp;
}
echo implode(" ", $x) . "\n";
}
echo "\n";
}
Note that a proper bubble sort algorithm will perform fewer iterations.
Bubble sort is basically simplified into a min() + shift (or sometimes swap) operation that occurs N times. So it's an O(n^2) algorithm.
Since this is for learning purposes I'm going to try to be as verbose as possible.
function getMin(Array &$array): Int {
$min = reset($array);
$minKey = null;
// Find the minimum value
foreach($array as $k => $n) {
if ($n < $min) {
$min = $n;
$minKey = $k;
}
}
// remove the minimum value from the array
$array[$k] = null;
$array = array_filter($array, function ($v) { return $v !== null; });
return $min;
}
$array = [9,7,5,3,0];
foreach ($array as $n => $value) {
// Find the min value in the array from Nth index onward
$min = getMin($array); // get the smallest value in the array and remove it.
$sorted[] = $min; // push it on to the new array
}
var_dump($sorted);
This gives you the expect result:
array(5) {
[0]=>
int(0)
[1]=>
int(3)
[2]=>
int(5)
[3]=>
int(7)
[4]=>
int(9)
}
Of course, this is not the way you would want to implement Bubble Sort, because it's a bit circuitous. Again, it's for educational purposes. You can inspect the $array as it's being modified at each step and the new $sorted as it's being built. Typically you would just swap the min/max values in place and use the same array (keeping track of the keys to rescan the array).
Like this...
// Unsorted $array
$array = [9,7,5,3,0];
// Sort the array
for ($lastKey = $i = 0, $len = count($array); $i < $len; $i++) {
// Scan for minimum value
for ($minKey = $j = $lastKey, $min = $array[$minKey]; $j < $len; $j++) {
if ($array[$j] < $min) {
$minKey = $j;
$min = $array[$j];
}
}
// Swap the values
$swap = $array[$lastKey];
$array[$lastKey] = $min;
$array[$minKey] = $swap;
// Update the scan position
$lastKey++;
}
var_dump($array); // Gives you [0,3,5,7,9]
You are performing unconditional position swapping, but you actually need to check if movement is required.
There is no shortage of tutorials that demonstrate a bubble sort in php. A quick good lead me to this one: https://www.w3resource.com/php-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-6.php which can be modified for your purposes.
PHP now offers "array destructuring" which means you no longer need to use a temporary holding variable while swapping.
Code: (Demo)
$x = [9,7,5,3,0];
$count = count($x) - 1;
for ($pass = 0; $pass < $count; ++$pass) {
for ($i = 0; $i < $count; ++$i) {
if ($x[$i] > $x[$i + 1]) {
[$x[$i + 1], $x[$i]] = [$x[$i], $x[$i + 1]];
}
$results[] = implode($x);
}
$results[] = "\n";
}
echo implode("\n", $results);
I am trying to get an factorial value of each item in array by using this method but this outputs only one value
can any body help me finding where i am doing wrong?
function mathh($arr, $fn){
for($i = 1; $i < sizeof($arr); $i++){
$arr2 = [];
$arr2[$i] = $fn($arr[$i]);
}
return $arr2;
}
$userDefined = function($value){
$x = 1;
return $x = $value * $x;
};
$arr = [1,2,3,4,5];
$newArray = mathh($arr, $userDefined);
print_r($newArray);
You're going to need a little recursion so in order to do that you need to pass the lambda function into itself by reference:
function mathh($arr, $fn){
$arr2 = []; // moved the array formation out of the for loop so it doesn't get overwritten
for($i = 0; $i < sizeof($arr); $i++){ // starting $i at 0
$arr2[$i] = $fn($arr[$i]);
}
return $arr2;
}
$userDefined = function($value) use (&$userDefined){ // note the reference to the lambda function $userDefined
if(1 == $value) {
return 1;
} else {
return $value * $userDefined($value - 1); // here is the recursion which performs the factorial math
}
};
$arr = [1,2,3,4,5];
$newArray = mathh($arr, $userDefined);
print_r($newArray);
The output:
Array
(
[0] => 1
[1] => 2
[2] => 6
[3] => 24
[4] => 120
)
I wanted to expand on this some since you're essentially (in this case) creating an array map. This could be handy if you're doing additional calculations in your function mathh() but if all you want to do is use the lambda function to create a new array with a range you could do this (utilizing the same lambda we've already created):
$mapped_to_lambda = array_map($userDefined, range(1, 5));
print_r($mapped_to_lambda);
You will get the same output, because the range (1,5) of the mapped array is the same as your original array:
Array
(
[0] => 1
[1] => 2
[2] => 6
[3] => 24
[4] => 120
)
I have an array like this
$data = array(51729,49359,47548,8242,8124,8716,19610,18030,15698);
And a index number
$index = 3;
Is there a simple way to iterate over $data to get
$first = array(51729,8242,19610)
$second = array(49359,8124,18030)
$third = array(47548,8716,15698)
Is array_chunk() and then foreach the chunks the way to go?
Edit: Here is how I made it with array_chunk()
$data = array(51729,49359,47548,8242,8124,8716,19610,18030,15698);
$index = 3;
$chunks = array_chunk($data, $index);
$first = array();
$second = array();
$third = array();
foreach($chunks as $out) {
$first[] = $out[0];
$second[] = $out[1];
$third[] = $out[2];
}
Edit 2: All of this is part of transforming a unidimensional array to multidimensional, naming will eventually be dynamic, based on values in array $labels. Index number is also going to change ($index is provided in original array).
To do it dynamically, you can create a multidimensional array.
// Your provided values
$data = array(51729,49359,47548,8242,8124,8716,19610,18030,15698);
$index = 3;
// Initialize your result array
$result = array();
// Loop through the array
foreach ($data as $key => $value) {
// Assign every nth to the appropriate sub-array
$result[$key % $index][] = $value;
}
// Print for validation
print_r($result);
Provides:
Array
(
[0] => Array
(
[0] => 51729
[1] => 8242
[2] => 19610
)
[1] => Array
(
[0] => 49359
[1] => 8124
[2] => 18030
)
[2] => Array
(
[0] => 47548
[1] => 8716
[2] => 15698
)
)
If you are looking to do this non-dynamically. i.e. it will always be named this way, you're looking to continuously iterate in this manner with little changing, then the following code will be sufficient.
$i = 1;
foreach($data as $arr){
switch($i){
case 1:
array_push($first, $arr);
break;
case 2:
array_push($second, $arr);
break;
case 3:
array_push($third, $arr);
break;
}
$i++;
if($i == 4){
$i = 1;
}
}
I want to sort my array which contains names as keys and numbers as values, a function for each of sorting by key and by value.
I'm aware of asort() and ksort(), but I want to do this manually. Originally I tried bubble sort, but quickly realised it didn't work as the keys were strings, not numbers.
How would I go about doing this? So if I have the array:
$ar = array("A" => 10, "D" => 25, "G" => 12)
How would I sort the array by value and by key? I can't find a way of cycling through it and sorting the two different values.
This code may be use full.
$ar = array("A" => 10, "D" => 25, "G" => 12,'B'=>11);
function bubbleSortValues($array){ // sort by value
$new_array = array_values($array); // get array values
$length = count($new_array);
// perform buuble sort
for ($outer = 0; $outer < $length; $outer++) {
for ($inner = 0; $inner < $length; $inner++) {
if ($new_array[$outer] < $new_array[$inner]) {
$tmp = $new_array[$outer];
$new_array[$outer] = $new_array[$inner];
$new_array[$inner] = $tmp;
}
}
}
// loop the sorted array and generate original array with keys and values
foreach($new_array as $key=>$value){
$sorted_array[array_search($value, $array)] = $value;
}
return $sorted_array;
}
function bubbleSortKeys($array){ //sort by key
$new_array = array_keys($array); // get array keys
$length = count($new_array);
// perform buuble sort
for ($outer = 0; $outer < $length; $outer++) {
for ($inner = 0; $inner < $length; $inner++) {
if ($new_array[$outer] < $new_array[$inner]) {
$tmp = $new_array[$outer];
$new_array[$outer] = $new_array[$inner];
$new_array[$inner] = $tmp;
}
}
}
// loop the sorted array and generate original array with keys and values
foreach($new_array as $key=>$value){
$sorted_array[$value] = $array[$value];
}
return $sorted_array;
}
echo "<pre>";
$values = bubbleSortValues($ar);
print_r($values);
$keys = bubbleSortKeys($ar);
print_r($keys);
OUT PUT:
Array
(
[A] => 10
[B] => 11
[G] => 12
[D] => 25
)
Array
(
[A] => 10
[B] => 11
[D] => 25
[G] => 12
)
Use strcmp to compare strings.
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... :(