Custom order array in PHP - php

I got this array:
$array = array('E1211','E2172','E2181','E233','E241','E286');
And I need to order first by first number-letter, i.e. E1, E2, E3, E4... followed by ordered numbers from lowest to highest.
Desired order would be: E1211, E233, E241, E286, E2172, E2181
If i do sort($array); the order will will be: "E1211", "E2172", "E2181", "E233", "E241" "E286".
If i do natsort($array); it will order by numbers from lowest to higest: "E233", "E241", "E286", "E1211", "E2172", "E2181"

Use usort() with a custom comparison function to split the strings and compare the portions.
<?php
$array = array('E1211','E2172','E2181','E233','E241','E286');
usort($array, function($a, $b){
$pfxA = substr($a,0,2); // Get the first two characters of each string
$pfxB = substr($b,0,2);
if ( $pfxA !== $pfxB) {return $pfxA<=>$pfxB;} // If they're not equal, return the spaceship comparison
return (int)substr($a,2)<=>(int)substr($b,2); // Prefixes are equal. Convert the rest to integers and return the spaceship comparison.
});
var_dump($array);
Output:
array(6) {
[0]=>
string(5) "E1211"
[1]=>
string(4) "E233"
[2]=>
string(4) "E241"
[3]=>
string(4) "E286"
[4]=>
string(5) "E2172"
[5]=>
string(5) "E2181"
}
See https://3v4l.org/5qts5

Actually what you want to do is mixing sorting with your own pattern with natsort(). I doubt if it can be accomplished by some oneliner, however it can be done with simple iteration in separate steps, that code does what I think you want (input data modified for better readibility).
<?php
$array = ['E3123', 'E1211', 'E2181', 'E241', 'E286', 'E2172', 'E233'];
$newArray = [];
$finalArray=[];
// Put it into associative array with required keys (two first chars)
foreach ($array as $item) {
$key = substr($item, 0, 2);
$newArray[$key][] = $item;
}
// sort new array by key (two first chars)
ksort($newArray);
// sort each subarray in natural order and put it to final array
foreach ($newArray as $key => $newItem) {
natsort($newArray[$key]);
$finalArray = array_merge($finalArray, $newArray[$key]);
}
// just check
var_dump($finalArray);
Result:
array (size=7)
0 => string 'E1211' (length=5)
1 => string 'E233' (length=4)
2 => string 'E241' (length=4)
3 => string 'E286' (length=4)
4 => string 'E2172' (length=5)
5 => string 'E2181' (length=5)
6 => string 'E3123' (length=5)

Related

How do I compare a string array to a numeric array?

dear users of StackOverflow. There is some problem.
Array 1:
array: 3 [▼
   0 => "8"
   1 => "13"
   2 => "15"
]
Array 2:
array: 16 [▼
   0 => 7
   1 => 8
   2 => 9
]
array_diff does not work, because in the first number, in the second string.
Please suggest any ideas for solving the issue. I will be happy with any comment. Many thanks.
You can use array_udiff to compare the arrays using a user-defined callback which converts the values to ints before comparing:
$array1 = array('8', '13', '15');
$array2 = array(7, 8, 9);
$diffs = array_udiff($array1, $array2, function ($a, $b) { return (int)$a - (int)$b; });
print_r($diffs);
Output:
Array
(
[1] => 13
[2] => 15
)
Update
It has been pointed out that the desired output hasn't been specified, so here is how to get all unique values:
$diffs1 = array_udiff($array1, $array2, function ($a, $b) { return (int)$a - (int)$b; });
$diffs2 = array_udiff($array2, $array1, function ($a, $b) { return (int)$a - (int)$b; });
$diffs = array_merge($diffs1, $diffs2);
print_r($diffs);
Output:
Array
(
[0] => 13
[1] => 15
[2] => 7
[3] => 9
)
and all matching values using array_uintersect:
$same = array_uintersect($array1, $array2, function ($a, $b) { return (int)$a - (int)$b; });
print_r($same);
Output:
Array
(
[0] => 8
)
Note
In PHP7 there is now the spaceship operator (<=>) which can also be used in the comparison function e.g.
$diffs = array_udiff($array1, $array2, function ($a, $b) { return (int)$a <=> (int)$b; });
You could convert the arrays using array map like this
$a1 = array_map('intval', $a1);
$a2 = array_map('intval', $a2);
Then do your array diff and what not.
#Nick's solution is a bit more elegant.
Because, it's not walking the arrays 2x more then you really need to. Of course if you know which is string then you could just convert that one, but I thought I would post another way to do it...
For testing you can simply do this
$a = [
"1",
"2" ,
"3"
];
var_dump($a);
var_dump(array_map('intval', $a));
Output
array(3) {
[0]=> string(1) "1"
[1]=> string(1) "2"
[2]=> string(1) "3"
}
array(3) {
[0]=> int(1)
[1]=> int(2)
[2]=> int(3)
}
Sandbox
And this shows that it does convert the values to string, which was pretty obvious, but I like examples. So there you go.
Cheers!
UPDATE
After doing some simple bench marking, with an array of 100,000 string numbers, and taking the average time from 100 iterations, it took apx 0.0072/seconds to convert the array back to ints:
//setup
$a = array_map('strval', range(0, 100000));
//get microtime as float after setup
$time = microtime(true);
//use the average of 100 conversion for consistency
$iterations = 100;
for($i=0;$i<$iterations; ++$i){
$b = array_map('intval', $a); //set to $b so we don't convert $a on our first iteration.
//check the first iteration, to make sure we have it setup correctly for our averaging
if($i==0)
echo number_format(
((microtime(true) - $time)),
4
)." \seconds\n\n";
}
echo number_format(
((microtime(true) - $time) / $itterations),
4
)." \seconds\n";
Output
0.0067 \seconds
//if these are close (which they are) we have everything setup right,
//it's better to take the average for speed testing.
//and I just wanted to double check that it was being done correctly
0.0072 \seconds
Sandbox
-note- the sandbox has only 134M of Ram for PHP (i've run it out of memory on purpose to test it.. lol)
<b>Fatal error</b>: Allowed memory size of 134217728 bytes exhausted
UPDATE1
It has been pointed out that the desired output hasn't been specified, so here is how to get all unique values:
If you want the Unique values from both arrays you can do
$unique = array_unique(array_replace($a1,$a2));
And if the arrays are unique beforehand you can just do array_replace because you will be combining 2 unique arrays replacing any in the one array that are duplicated in the other. Therefore the result will be the unique combination of 2 unique arrays, if that makes sense.
This is a non-issue. PHP DOES NOT require a workaround for string numbers versus non-string numbers.
Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In other words: when the string representation is the same.
Source: https://www.php.net/manual/en/function.array-diff.php
Here's my output in PHP 7.4.7. (The same output happens when I run it in PHP 5.6, and that's the earliest version I have installed right now.)
php > var_dump(array_diff([1,2,3], ["2"]));
array(2) {
[0]=>
int(1)
[2]=>
int(3)
}

Create php array from strings that contains bracket literals

I have a number of strings, that contain the bracket literals:
0 => string '[139432,97]' (length=18)
1 => string '[139440,99]' (length=18)
I need to create string arrays of [139432,97] and [139440,99].
I've tried using json_decode(), but while it works, it creates arrays as float or int using the above data, however I want them as strings.
array (size=2)
0 => float 139432
1 => int 97
array (size=2)
0 => float 139440
1 => int 97
You can put double quotes around the values e.g.
0 => string '["139432","97"]' (length=22)
1 => string '["139440","99"]' (length=22)
This way when you json_decode they should be strings.
Edit:
OK I thought you could control the input - if not then a simple trim and explode could do:
explode(',', trim('[139432,97]', '[]'));
array(2) {
[0]=>
string(6) "139432"
[1]=>
string(2) "97"
}
Is that enough?
Just combining what you already now (json_decode) and what #AlixAxel suggested here you can extract those values to string link:
$subject = '[139432,97]';
$convertedToArrayOfStrings = array_map('strval', json_decode($subject));
or
$convertedToArrayOfString = array_map(function($item){return (string) $item;}, json_decode($subject));
for better performance, see the comment bellow please :)
Why not try with loop and use explode function:
$array = array('139432,97', '139440,99');
$finalArray = array();
$i = 0;
foreach ($array as $arr) {
$explode = explode(",", $arr);
$j = 0;
foreach ($explode as $exp) {
$finalArray[$i][$j] = (int)$exp;
$j++;
}
$i++;
}

properly render an array of numeric values, not an array with strings

I have this code in my symfony controller:
$em=$this->getDoctrine()->getManager();
$queryIndex = $em->createQuery( 'SELECT g.index
FROM MySpaceMyBundle:Graphique g');
$result = $queryIndex->getArrayResult();
$arrayResult = array_map('current', $result);
var_dump($arrayResult);
return $this->render('MySpaceMyBundle:MyFolder:myTemplate.html.twig');
With my var_dump, I have this result:
array (size=10)
0 => string '1700.000' (length=8)
1 => string '1200.000' (length=8)
2 => string '1200.000' (length=8)
3 => string '1304.000' (length=8)
4 => string '1800.000' (length=8)
5 => string '2012.000' (length=8)
6 => string '2048.000' (length=8)
7 => string '1048.000' (length=8)
8 => string '3000.000' (length=8)
9 => string '5421.000' (length=8)
But for the obHighchartBundle (using highchart.js) the result I want is:
[1700,1200,1200,1304,1800,2012,2048,1048,3000,5421]
How can I proceed?
Note that I need to pass a numeric array (the values are decimal types in my database), not array with strings.
Like this?
$result = [];
foreach ($arrayResult as $value) {
$result[] = (int) $value
}
var_dump($result);
You can use a tiny tips like array_walk function to cast your values as float to prevent highchart issue. See the documentation for this function:
http://php.net/manual/fr/function.array-walk.php
Here an example of the tiny function :
<?php
function forceFloat (&$aItems) {
$aItems = (float) $aItems;
}
$arrayResult = array("1.00","4.55","39494");
var_dump($arrayResult);
array_walk($arrayResult, 'forceFloat');
var_dump($arrayResult);
?>
The output :
array(3) {
[0]=>
string(4) "1.00"
[1]=>
string(4) "4.55"
[2]=>
string(5) "39494"
}
array(3) {
[0]=>
float(1)
[1]=>
float(4.55)
[2]=>
float(39494)
}
Best Regards,
TGA

Using preg_replace on an array

I have a relatively large array of elements which I want to search for a string and replace any matches. I'm currently trying to do this using preg_replace and regular expressions:
preg_replace("/\d?\dIPT\.\w/", "IPT", $array);
I want to get all values which match either 00IPT.A or 0IPT.A (with 0 representing any numerical character and A representing any letter) and replace them with IPT. However, I'm getting array to string conversion notices. Is there any way to get preg_replace to accept an array data source? If not, is there any other way I could achieve this?
The documentation says that preg_replace should be able to accept array sources — this is the reason I'm asking.
The string or an array with strings to search and replace.
If subject is an array, then the search and replace is performed on every entry of subject, and the return value is an array as well.
The array is multidimensional if that helps (has multiple arrays under one main array).
preg_replace doesn't modify in place. To permanently modify $array, you simply need to assign the result of preg_replace to it:
$array = preg_replace("/\d{1,2}IPT\.\w/", "IPT", $array);
works for me.
$array = array('00IPT.A', '0IPT.A');
$array = preg_replace("/\d{1,2}IPT\.\w/", "IPT", $array);
var_dump($array);
// output: array(2) { [0]=> string(3) "IPT" [1]=> string(3) "IPT" }
Note: the \d{1,2} means one or two digits.
If you want to do this to a two-dimensional array, you need to loop through the first dimension:
$array = array( array('00IPT.A', 'notmatch'), array('neither', '0IPT.A') );
foreach ($array as &$row) {
$row = preg_replace("/\d{1,2}IPT\.\w/", "IPT", $row);
}
var_dump($array);
output:
array(2) {
[0]=> array(2) {
[0]=> string(3) "IPT"
[1]=> string(8) "notmatch"
}
[1]=> &array(2) {
[0]=> string(7) "neither"
[1]=> string(3) "IPT"
}
}
Note that you have to loop through each row by reference (&$row) otherwise the original array will not be modified.
Your value does not sit in the array as a simple element but as a subset right? Like so?
array (
array ('id' => 45, 'name' => 'peter', 'whatyouarelookingfor' => '5F'),
array ('id' => 87, 'name' => 'susan', 'whatyouarelookingfor' => '8C'),
array ('id' => 92, 'name' => 'frank', 'whatyouarelookingfor' => '9R')
)
if so:
<?php
foreach ($array as $key => $value) {
$array[$key]['whatyouarelookingfor'] =
preg_replace("/\d?\dIPT\.\w/", "IPT", $value['whatyouarelookingfor']);
}
Or if more elements have this, just go broader:
<?php
foreach ($array as $key => $value) {
$array[$key] =
preg_replace("/\d?\dIPT\.\w/", "IPT", $value);
}
your $array contains some further arrays. preg_replace works fine with arrays of strings, but not with arrays of arrays [of arrays...] of strings.

Understanding PHP arrays, specifically example given

I am new to PHP and arrays and am wanting to understand the following array. I would also like to learn how I would go about assigning values to two particular array elements in PHP, i.e.:
["_gravity_form_lead"]=> array(5) { [1]=> string(4) "1000" [3]=> string(6) "strips" [2]=> string(2) "rp" [5]=> string(0) "" [6]=> string(0) "" }
1) What is the correct notation to define this array?
2) For the two array elements that are "", i.e.
[5]=> string(0) "" [6]=> string(0) ""
In PHP, how would I go about assigning values to these two array elements, that are NULL?
Hope this makes you understand ,
$array_before = array('_gravity_form_lead' => array( '1000', "strips", "rp", '', ''));
echo '<pre>';
echo 'This what it looks after print_r'.'<br>';
print_r($array_before);
echo '</pre>';
I don't see anything different and special than its said in the documentation
http://php.net/manual/en/language.types.array.php
Anyway, the concrete situation is.
$_gravity_form_lead = array(1=>1000, 3=>'strips', 2=>'rp', 5=>'', 6=>'');
As said in the documentation
Creating/modifying with square bracket syntax ¶
An existing array can be modified by explicitly setting values in it.
This is done by assigning values to the array, specifying the key in brackets. The key can also be omitted, resulting in an empty pair of brackets ([]).
$arr[key] = value;
You do modify the ones you need with [ ]
In this particular case:
$_gravity_form_lead[5] = 'something';
$_gravity_form_lead[6] = 'something else';
In order you want to modify all empty strings, you can iterate through the array and modify. You have two options while iterating - using reference &, which will modify the existent one, or creating new array.
foreach ($_gravity_form_lead as &$val) {
if ($val == '') {
$val = 'something';
}
}
The output after doing this is
var_dump($_gravity_form_lead);
/*
* array (size=5)
1 => int 1000
3 => string 'strips' (length=6)
2 => string 'rp' (length=2)
5 => string 'something' (length=9)
6 => &string 'something' (length=9)
*/
It would be defined somewhat like,
$arrayName = array('_gravity_form_lead' => array( 1=>'1000', 3=>"strips", 2=>"rp", 5=>'', 6=>''));
/* assign null instead of '' */
$arrayName['_gravity_form_lead'][5] = NULL;
$arrayName['_gravity_form_lead'][6] = NULL;

Categories