str_replace() and strpos() for arrays? - php

I'm working with an array of data that I've changed the names of some array keys, but I want the data to stay the same basically... Basically I want to be able to keep the data that's in the array stored in the DB, but I want to update the array key names associated with it.
Previously the array would have looked like this: $var_opts['services'] = array('foo-1', 'foo-2', 'foo-3', 'foo-4');
Now the array keys are no longer prefixed with "foo", but rather with "bar" instead. So how can I update the array variable to get rid of the "foos" and replace with "bars" instead?
Like so: $var_opts['services'] = array('bar-1', 'bar-2', 'bar-3', 'bar-4');
I'm already using if(isset($var_opts['services']['foo-1'])) { unset($var_opts['services']['foo-1']); } to get rid of the foos... I just need to figure out how to replace each foo with a bar.
I thought I would use str_replace on the whole array, but to my dismay it only works on strings (go figure, heh) and not arrays.

The idea:
Get a list of all your array keys
Modify each one of them as you choose
Replace the existing keys with the modified ones
The code:
$keys = array_keys($arr);
$values = array_values($arr);
$new_keys = str_replace('foo', 'bar', $keys);
$arr = array_combine($new_keys, $values);
What this actually does is create a new array which has the same values as your original array, but in which the keys have been changed.
Edit: updated as per Kamil's comment below.

For the values you've provided
$var_opts['services'] = array('foo-1', 'foo-2', 'foo-3', 'foo-4');
var_dump($var_opts['services']);
foreach($var_opts['services'] as &$val) {
$val = str_replace('foo', 'bar', $val);
}
unset($val);
var_dump($var_opts['services']);
or if you want to change the actual keys
$var_opts['services'] = array('foo-1' => 1, 'foo-2' => 2, 'foo-3' => 3, 'foo-4' => 4);
var_dump($var_opts['services']);
foreach($var_opts['services'] as $i => $val) {
unset($var_opts['services'][$i]);
$i = str_replace('foo', 'bar', $i);
$var_opts['services'][$i] = $val;
}
var_dump($var_opts['services']);

Related

PHP removing a specific array from a multidimensional array

I have a multidimensional array in PHP where I need to remove one array based on the value of an item in one of the arrays:
Example Array
array(
"0"=>array("0"=>"joe", "1"=>"2018-07-18 09:00:00"),
"1"=>array("0"=>"tom", "1"=>"2018-07-17 09:00:00"),
"2"=>array("0"=>"joe", "1"=>"2018-07-14 09:00:00")
)
I know that I want to remove the array that contains joe in key 0, but I only want to remove the array that contains joe with the most current date in key1. The following output is what I'm trying to accomplish:
array(
"0"=>array("0"=>"tom", "1"=>"2018-07-17 09:00:00"),
"1"=>array("0"=>"joe", "1"=>"2018-07-14 09:00:00")
)
Is there a simple way to do this in PHP aside from looping through each array?
Here is a non looping method that uses array_intersect and array_column to find the "Joe's" and then deletes the maximum array_key since I first sort the array on dates.
usort($arr, function($a, $b) {
return $a[1] <=> $b[1];
}); // This returns the array sorted by date
// Array_column grabs all the names in the array to a single array.
// Array_intersect matches it to the name "Joe" and returns the names and keys of "Joe"
$joes = array_intersect(array_column($arr, 0), ["joe"]);
// Array_keys grabs the keys from the array as values
// Max finds the maximum value (key)
$current = max(array_keys($joes));
unset($arr[$current]);
var_dump($arr);
https://3v4l.org/mah6K
Edit forgot to add the array_values() if you want to reset the keys in the array.
Just add $arr = array_values($arr); after the unset.
I would go about it like this:
<?php
$foo = array(
"0"=>array("0"=>"joe", "1"=>"2018-07-18 09:00:00"),
"1"=>array("0"=>"tom", "1"=>"2018-07-17 09:00:00"),
"2"=>array("0"=>"joe", "1"=>"2018-07-14 09:00:00")
);
$tmp = [];
foreach($foo as $k => $v) {
if ($v[0] === 'joe') {
$tmp[$v[1]] = $k;
}
}
if (!empty($tmp)) {
sort($tmp); //think that is sane with date format?
unset($foo[reset($tmp)]);
}
var_dump($foo);
Not sure if you don't want to loop on principal or what... I tend to go for readability. Find all occurrences of joe. Sort on date. Remove the most recent by key.

Keep duplicate keys in array

I am getting data from whois and breaking the data up and putting it into an array with keys but some need multiple keys the same name is there anyway i can add number onto the end of the same named keys to make them unique?
here is my code so far
$test1 =$check_domain->find_whois_details("be.co");
$rows = explode("\n", $test1);
$arr = array('info'=>"");
foreach($rows as $row) {
$posOfFirstColon = strpos($row, ":");
if($posOfFirstColon === FALSE)
$arr['info'] .= $row;
else
$arr[substr($row, 0, $posOfFirstColon)] = trim(substr($row, $posOfFirstColon+1));
}
$a = array_map('trim', array_keys($arr));
$b = array_map('trim', $arr);
$arr = array_combine($a, $b);
print($arr["Registry Expiry Date"]);
It seems like a more manageable solution would be to change your storage structure to a multidimensional array rather than a flat array.
$arr[substr($row, 0, $posOfFirstColon)][] = trim(substr($row, $posOfFirstColon+1));
In this structure, each name would correspond to an array containing one or more values. This way, the key retains its original value, which would become less meaningful if you appended some arbitrary value to it to keep it unique.
This may not work for your specific scenario, but it's generally a better representation for grouping a set of data by a specific property.
bool array_key_exists ( mixed $key , array $array )
array_key_exists — Checks if the given key or index exists in the array
<?php
$search_array = array('first' => null, 'second' => 4);
// returns true
array_key_exists('first', $search_array);
?>
Using this function, you can check if the key is already existing, in that case just concatenate a number after the key you're inserting !

How to get the exact value of the last array index in PHP?

Currently i have an array $newArr with some elements as shown in picture below. How do I know the last digit of the array index (highlighted in yellow)?
This is important because, if later I wanted to insert a new record into this $newArr array, I could just
$newArr[$the_variable_that_holds_the_last_digit + 1] = ['foo', 'bar'];
otherwise the whole array overwrite if
$newArr = ['foo', 'bar'];
I think you are looking for end pointer
$array = array(
'a' => 1,
'b' => 2,
'c' => 3,
);
end($array); // it will point to last key
$key = key($array); // get the last key using `key`
Assuming you have the numerically indexed array, the last index on your array is :
$last_index = count($newArr) -1;
if However your keys are not sequential, you can do this:
end($newArr);
$last_key = key($newArr);
I think you can try this
$array = end($newArr);
$last_index = key($array);//Its display last key of array
For more details, please follow this link.
If the only reason is to not overwrite the values you can use [] which means add new value.
$arr = [1,2,3,4];
var_dump($arr);
// incorrect way:
$arr = [1,2];
var_dump($arr);
//correct way
$arr = [1,2,3,4];
$arr[] = [1,2];
var_dump($arr);
See here for output: https://3v4l.org/ZTg28
The "correct way" will in the example above input a new array in the array.
If you want to add only the values you need to insert them one at the time.
$arr[] = 1;
$arr[] = 2;

PHP - Get array value with a numeric index

I have an array like:
$array = array('foo' => 'bar', 33 => 'bin', 'lorem' => 'ipsum');
echo native_function($array, 0); // bar
echo native_function($array, 1); // bin
echo native_function($array, 2); // ipsum
So, this native function would return a value based on a numeric index (second arg), ignoring assoc keys, looking for the real position in array.
Are there any native function to do that in PHP or should I write it?
Thanks
$array = array('foo' => 'bar', 33 => 'bin', 'lorem' => 'ipsum');
$array = array_values($array);
echo $array[0]; //bar
echo $array[1]; //bin
echo $array[2]; //ipsum
array_values() will do pretty much what you want:
$numeric_indexed_array = array_values($your_array);
// $numeric_indexed_array = array('bar', 'bin', 'ipsum');
print($numeric_indexed_array[0]); // bar
I am proposing my idea about it against any disadvantages array_values( ) function, because I think that is not a direct get function.
In this way it have to create a copy of the values numerically indexed array and then access. If PHP does not hide a method that automatically translates an integer in the position of the desired element, maybe a slightly better solution might consist of a function that runs the array with a counter until it leads to the desired position, then return the element reached.
So the work would be optimized for very large array of sizes, since the algorithm would be best performing indices for small, stopping immediately. In the solution highlighted of array_values( ), however, it has to do with a cycle flowing through the whole array, even if, for e.g., I have to access $ array [1].
function array_get_by_index($index, $array) {
$i=0;
foreach ($array as $value) {
if($i==$index) {
return $value;
}
$i++;
}
// may be $index exceedes size of $array. In this case NULL is returned.
return NULL;
}
Yes, for scalar values, a combination of implode and array_slice will do:
$bar = implode(array_slice($array, 0, 1));
$bin = implode(array_slice($array, 1, 1));
$ipsum = implode(array_slice($array, 2, 1));
Or mix it up with array_values and list (thanks #nikic) so that it works with all types of values:
list($bar) = array_values(array_slice($array, 0, 1));

Populating PHP list() with values in an array

I have an array:
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
I want to have the elements in that array appear as the variables in my list():
list($foo, $bar, $bash, $monkey, $badger) = $data;
Without actually specifying the variables, I tried;
list(implode(",$", $arr)) = $data; and
list(extract($arr)) = $data;
But they don't work, I get:
Fatal error: Can't use function return value in write context
Does anyone have any idea whether this is possible?
UPDATE: more context:
I am getting a CSV of data from an API, the first row is column names, each subsequent row is data. I want to build an associative array that looks like this:
$data[0]['colname1'] = 'col1data';
$data[0]['colname2'] = 'col2data';
$data[0]['colname3'] = 'col3data';
$data[1]['colname1'] = 'col1data';
$data[1]['colname2'] = 'col2data';
$data[1]['colname3'] = 'col3data';
Before I do that, however, I want to make sure I have all the columns I need. So, I build an array with the column names I require, run some checks to ensure the CSV does contain all the columns I need. Once thats done, the code looks somewhat like this (which is executed on a foreach() for each row of data in the CSV):
//$data is an array of data WITHOUT string indexes
list( $col1,
$col2,
$col3,
...
$col14
) = $data;
foreach($colNames AS $name)
{
$newData[$i][$name] = $$name;
}
// Increemnt
$i++;
As I already HAVE an array of column name, I though it would save some time to use THAT in the list function, instead of explicitly putting in each variable name.
The data is cleaned and sanitised elsewhere.
Cheers,
Mike
I want to have the elements in that array appear as the variables in my list():
i think there is your problem in understanding. list() does not create a new list structure or variable, it can only be used to assign many variables at once:
$arr = array(1, 2, 3);
list($first, $second, $third) = $arr;
// $first = 1, $second = 2, $third = 3
see http://php.net/list for more information.
you are probably looking for an associative array. you can create it with the following code:
$arr = array('first' => 1, 'second' => 2, 'third' => 3);
// $arr['first'] = 1, …
If some rows in your input file are missing columns, you can't really know which one is missing. Counting the number of values and aborting or jumping to next row when less than expected should be enough.
... unless you set the rule that last columns are optional. I'll elaborate on this.
Your code sample is far for complete but it seems that your problem is that you are using arrays everywhere except when matching column names to cell values. Use arrays as well: you don't need individual variables and they only make it harder. This is one of the possible approaches, not necessarily the best one but (I hope) clear enough:
<?php
$required_columns = array('name', 'age', 'height');
$input_data = array(
array('John', 33, 169),
array('Bill', 40, 180),
array('Ashley', 21, 155),
array('Vincent', 13), // Incomplete record
array('Michael', 55, 182),
);
$output = array();
foreach($input_data as $row_index => $row){
foreach($required_columns as $col_index => $column_name){
if( isset($row[$col_index]) ){
$output[$row_index][$column_name] = $row[$col_index];
}
}
}
print_r($output);
?>
I've used $row_index and $col_index for simplicity.
Original answer, for historical purposes only ;-)
I can't really understand your specs but PHP features variable variables:
<?php
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
foreach($arr as $i){
$$i = $i;
}
?>
Now your script has these variables available: $foo, $bar... It's quite useless and potentially dangerous but it does what you seem to need.
You are trying to use a language construct in a manner in which it's not meant to be used. Use variable variables as Alvaro mentioned.
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
foreach ($arr as $index => $key) {
$$key = $data[$index];
}
or
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
$result = array();
foreach ($arr as $index => $key) {
$result[$key] = $data[$index];
}
extract($result);
In short, do not use "list", use arrays and associated arrays. Write helper functions to make your code clearer.
why not immediatly call the vars like
$arr['foo']
or
$arr[0]
If you want to extract the elements of $data into the current context, you can do that with extract. You might find it useful to call array_intersect_key first to pare down $data to the elements that you want to extract.
May be try like this :
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
$data = "$".implode(",", $arr);
echo str_replace(",", ",$", $data);

Categories