Using preg_replace on an array - php

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.

Related

Custom order array in 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)

PHP only get values from multidimensional array where keys intersect with other array

I think this should be something simple, but I can't find a way to do it.
I have two arrays, one with colors and ids
$color_ids = [
'green' => [1,2,3],
'blue' => [4,5],
'red' => [6],
'pink' => [7,8,9],
'yellow' => [10]
];
and others with selection.
$select = ['green', 'red', 'yellow'];
Then I need the ids where intersects keys between $color_ids and $select. This should be the result (a simple linear array):
$results = [1,2,3,6,10];
I've tried this:
$result = array_values(array_intersect_key( $color_ids, array_flip($select ) ) );;
But I get multidimensional array:
array(3) {
[0]=> array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
[1]=> array(1) { [0]=> int(6) }
[2]=> array(1) { [0]=> int(10) }
}
I get the same result with this:
$result = [];
foreach ($select as $key) {
if (isset($color_ids[$key]))
$result[] = $color_ids[$key];
}
How can I get a simple linear array with ids?
1) Iterate over the key array
2) Merge all the arrays into one using array_merge
$select = ['green', 'red', 'yellow'];
$finalArray=[];
foreach($select as $value){
$finalArray= array_merge($finalArray,$color_ids[$value]);
}
echo "<pre>";
print_r($finalArray);
Output:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 6
[4] => 10
)
You can use array_merge with the ... operator which is a common flattening technique demonstrated here.
array_merge(...$result);
Array Merge documentation.
Splat Operator documentation.
with foreach
$result = [];
foreach($color_ids as $color => $ids){
$result = array_merge($result, in_array($color, $select) ? $ids : []);
}
If you are looking for a fully "functional style" solution, here's one.
Set up your filtering array ($select) so that it has keys like the master array's keys. In other words, flip the values into keys.
Then swiftly filter the master array using array_intersect_key().
Then to flatten the remaining data, prepend the splat/spread operator and call array_merge().
Until you are on a php version that allows associative arrays to be spread, then you'll need to call array_values() to reindex the first level keys so that the spread operator doesn't choke.
Code: (Demo)
var_export(
array_merge(
...array_values(
array_intersect_key(
$color_ids,
array_flip($select)
)
)
)
);
Or if you prefer jumble the syntax into a single line:
var_export(array_merge(...array_values(array_intersect_key($color_ids, array_flip($select)))));
Although a foreach() may perform a few nanoseconds faster than functional programming, you are never going to notice on such small data sets. One benefit of this coding style is that you don't have to name any temporary variables to push qualifying data into. In other words you can feed this directly into a return statement inside of a function which I find to be very tidy.
Alternatively, if you don't mind generating a result variable, then iterated array_push() calls while spreading the matching nominated color_id value is pretty simple. This technique is different in that if $select contains a color that is not a key in $color_id, then php will bark at you!
Code: (Demo)
$result = [];
foreach ($select as $color) {
array_push($result, ...$color_ids[$color]);
}
var_export($result);
Both techniques offer the same result.

Sorting an array by the values of another array

I have a some messy data coming in from a feed, and am trying to figure out how to sort it correctly. I posted a simplified example below. I'd like to sort the people array alphabetically by the Group name.
$people = array(
"category_id_1" => array (
"Mark",
"Jenny",
"Andrew"
),
"category_id_2" => array (
"John",
"Lewis",
"Andrea"
),
"category_id_3" => array (
"Hannah",
"Angie",
"Raleigh"
)
);
$categories = array(
"category_id_1" => "Group B",
"category_id_2" => "Group C",
"category_id_3" => "Group A"
);
Ideally, the end result would be
$people = array(
"category_id_3" => array ( // Group A
"Hannah",
"Angie",
"Raleigh"
),
"category_id_1" => array ( // Group B
"Mark",
"Jenny",
"Andrew"
),
"category_id_2" => array ( // Group C
"John",
"Lewis",
"Andrea"
)
);
I've been spinning my wheels for a while now, and the closest I have gotten is this uasort, which still isn't doing the trick.
uasort($people, function ($a, $b) {
return strcmp($categories[$a], $categories[$b]);
});
Thanks so much for any help.
This can be achieved in a simpler way by taking advantage of array_replace:
// Work on a copy just to be sure the rest of your code is not affected
$temp_categories = $categories;
// Sort categories by name
asort($temp_categories);
// Replace the values of the sorted array with the ones in $people
$ordered_people = array_replace($temp_categories, $people);
You want to sort $people by its keys not its values. You can use uksort for this. Additionally you need to make $categories available in your function. I prefer use for that; but you could also make it a global variable. Final code:
uksort($people, function ($a,$b) use ($categories) {
return strcmp($categories[$a], $categories[$b]);
});
Manual for uksort
use language construct. Before example 3.
I think what you need is to Asort categories and the use that sorted array in a foreach.
Asort($categories);
Foreach($categories as $key => $group){
$new[$key] =$people[$key];
}
Var_dump($new);
https://3v4l.org/kDAQW
Output:
array(3) {
["category_id_3"]=> array(3) {
[0]=> "Hannah"
[1]=> "Angie"
[2]=> "Raleigh"
}
["category_id_1"]=> array(3) {
[0]=> "Mark"
[1]=> "Jenny"
[2]=> "Andrew"
}
["category_id_2"]=>array(3) {
[0]=> "John"
[1]=> "Lewis"
[2]=> "Andrea"
}
}
Try this(tested and working):
asort($categories);
$sorted = array();
foreach ($categories as $key => $value)
$sorted[$key]=$people[$key];
A better shorter approach:(tested and working)
asort($categories);
$result = array_merge($categories,$people);
The second method takes advantage of the fact that array_merge function replace the values in the first array with those in the second one when keys are the same.
warning : The second approach will not work if the keys are numbers. Use only string keys with it. Furthermore if the categories array has entries without corresponding entries in the people array they will be copied to the result
To solve this problem we use array_replace :
asort($categories);
$result = array_replace($categories,$people);
Var_dump($result);// tested and working

extract selected array values based on list php

I have a list of array keys in form of a string
"hasAddStrict,freqItems,freqAmount,freqUnit,freqFirstDayOfWeek"
Now, want to extract only those values, i.e $myarray['hasAddstrict'] should become $hasAddStrict, etc.
Is there a short way to do it? My rather dirty solution:
$ff = explode(',' ,"hasAddStrict,freqItems,freqAmount,freqUnit,freqFirstDayOfWeek");
foreach ( $ff as $key){ $ff[$key] = $SERVICE[$key] ; }
extract($ff);
I agree with Jeff that there isn't really a better way, and that keeping the variables as an array is probably a better idea, but you could wrap it up in a function for convenience (tested in php 5.6):
<?php
function array_extract(array $assoc_array, $keys_list)
{
return array_intersect_key($assoc_array, array_flip(explode(',', $keys_list)));
}
extract(array_extract($SERVICE, "hasAddStrict,freqItems,freqAmount,freqUnit,freqFirstDayOfWeek"));
When tested as follows:
$SERVICE = [
'hasAddStrict' => 123,
'freqItems' => 456,
'freqAmount' => 789,
'freqUnit' => 'abc',
'freqFirstDayOfWeek' => 'def',
];
extract(array_extract($SERVICE, "hasAddStrict,freqItems,freqAmount,freqUnit,freqFirstDayOfWeek"));
var_dump($hasAddStrict, $freqItems, $freqAmount, $freqUnit, $freqFirstDayOfWeek);
You get output:
int(123)
int(456)
int(789)
string(3) "abc"
string(3) "def"

How to remove duplicate values in an array

I want to remove duplicate values from an array.
Here is my array
$arr=array([0]=>123,[1]=>223,[2]=>323,[3]=>123,[4]=>223);
For removing duplicate values, I used array_unique() function, but it still shows the same array.
Is there any method to solve this problem?
use array_unique()
<?php
$arr=array([0]=>123,[1]=>223,[2]=>323,[3]=>123,[4]=>223);
$result = array_unique($arr);
print_r($result);
?>
Your code works fine for me.
$arr = array(0 => 123, 1 => 223, 2 => 323, 3 => 123, 4 => 223);
var_dump(array_unique($arr));
Output
array(3) {
[0]=>
int(123)
[1]=>
int(223)
[2]=>
int(323)
}
CodePad.
Note that array_unique() returns a new array, it doesn't take the array by reference, so you'll need to assign the returned array somewhere.
try this
$arrUnique = array_unique($arr);
print_r($arrUnique);

Categories