PHP Replace and edit array elements from keywords - php

I have the following input:
$input = [
0 => '$id000001',
1 => '$id000002',
2 => '$id000003',
3 => 'Alexandre'
];
$keywords = [
'$id000001' => 'function_name($+2)',
'$id000002' => '$user',
'$id000003' => '$-1 = $+1'
];
I would like to implement a function that will replace $input elements with $keywords elements, with the following output:
[
0 => 'function_name($+2)',
1 => '$user',
2 => '$-1 = $+1',
3 => 'Alexandre'
];
Here is the point, my function have to replace all $(+|-)[0-9]+ elements (like $+2, $-1, ...) with $input element value (after it has been replaced) and then remove them. The number is the row offset index :
$-1 = $+1 will be replaced with $user = 'Alexandre'
function_name($+2) will be replaced with $-1 = $+1 (wich is $user = 'Alexandre')
So, the final output will be:
[
0 => function_name($user = 'Alexandre')
]

Ok, after trying to fix infinite recurtions, i found this :
function translate($input, array $keywords, $index = 0, $next = true)
{
if ((is_array($input) === true) &&
(array_key_exists($index, $input) === true))
{
$input[$index] = translate($input[$index], $keywords);
if (is_array($input[$index]) === true)
$input = translate($input, $keywords, $index + 1);
else
{
preg_match_all('/\$((?:\+|\-)[0-9]+)/i', $input[$index], $matches, PREG_SET_ORDER);
foreach ($matches as $match)
{
$element = 'false';
$offset = ($index + intval($match[1]));
$input = translate($input, $keywords, $offset, false);
if (array_key_exists($offset, $input) === true)
{
$element = $input[$offset];
unset($input[$offset]);
}
$input[$index] = str_replace($match[0], $element, $input[$index]);
}
if (empty($matches) === false)
$index--;
if ($next === true)
$input = translate(array_values($input), $keywords, $index + 1);
}
}
else if (is_array($input) === false)
$input = str_replace(array_keys($keywords), $keywords, $input);
return $input;
}
Maybe, someone could find some optimizations.

Related

PHP Regular Expression preg_match from Array with Multine doesn't match all block

Wondering if anyone out there can help me with the following regular expression, i can't match the block multine CF.{Coordonnees Abonne}: when used in PHP's preg_match function.
What is weird is when I do regex online it seems to work despite the block is in another group regex101 example
Here is the code : source code
<?php
$response = array(
1 => 'CF.{Temps}: 1',
2 => 'CF.{Etat}: return',
3 => 'CF.{Code}: 2',
4 => 'CF.{Values}: plaque',
5 => '',
6 => 'CF.{Coordonnees}: LA PERSONNE',
7 => ' ',
8 => ' 10000 LA VILLE',
9 => ' ',
10 => ' 0500235689',
11 => ' 0645788923',
12 => ' Login : test#mail.com',
13 => ' Password : PassWord!',
14 => '',
15 => 'CF.{Groupe}: 3',
16 => 'CF.{Date}: 4',
);
print_r(parseResponseBody($response));
function parseResponseBody(array $response, $delimiter = ':')
{
$responseArray = array();
$lastkey = null;
foreach ($response as $line) {
if(preg_match('/^([a-zA-Z0-9]+|CF\.{[^}]+})' . $delimiter . '\s(.*)|([a-zA-Z0-9].*)$/', $line, $matches)) {
$lastkey = $matches[1];
$responseArray[$lastkey] = $matches[2];
}
}
return $responseArray;
}
?>
Output :
Array
(
[CF.{Temps}] => 1
[CF.{Etat}] => return
[CF.{Code}] => 2
[CF.{Values}] => plaque
[CF.{Coordonnees}] => LA PERSONNE
[] =>
[CF.{Groupe}] => 3
[CF.{Date}] => 4
)
And there is the wanted final result that i need to extract :
Array
(
[CF.{Temps}] => 1
[CF.{Etat}] => return
[CF.{Code}] => 2
[CF.{Values}] => plaque
[CF.{Coordonnees}] => LA PERSONNE
10000 LA VILLE
0500235689
0645788923
Login : test#mail.com
Password : PassWord!
[CF.{Groupe}] => 3
[CF.{Date}] => 4
)
You have to check if current value at iteration starts with a block or not. Not both at same time though:
function parseResponseBody(array $response, $delimiter = ':') {
$array = [];
$lastIndex = null;
foreach ($response as $line) {
if (preg_match('~^\s*(CF\.{[^}]*})' . $delimiter . '\s+(.*)~', $line, $matches))
$array[$lastIndex = $matches[1]] = $matches[2];
elseif ((bool) $line)
$array[$lastIndex] .= PHP_EOL . $line;
}
return $array;
}
Live demo
I would do that this way:
function parse($response, $del=':', $nl="\n") {
$pattern = sprintf('~(CF\.{[^}]+})%s \K.*~A', preg_quote($del, '~'));
foreach ($response as $line) {
if ( preg_match($pattern, $line, $m) ) {
if ( !empty($key) )
$result[$key] = rtrim($result[$key]);
$key = $m[1];
$result[$key] = $m[0];
} else {
$result[$key] .= $nl . $line;
}
}
return $result;
}
var_export(parse($response));
demo
The key is stored in the capture group 1 $m[1] but the whole match $m[0] returns only the value part (the \K feature discards all matched characters on its left from the match result). When the pattern fails, the current line is appended for the last key.
The regex is fine, you just need to handle the case when there is no key:
function parseResponseBody(array $response, $delimiter = ':')
{
$responseArray = array();
$key = null;
foreach ($response as $line) {
if(preg_match('/^([a-zA-Z0-9]+|CF\.{[^}]+})' . $delimiter . '\s(.*)|([a-zA-Z0-9].*)$/', $line, $matches)) {
$key = $matches[1];
if(empty($key)){
$key = $lastKey;
$responseArray[$key] .= PHP_EOL . $matches[3];
}else{
$responseArray[$key] = $matches[2];
}
$lastKey = $key;
}
}
return $responseArray;
}
https://3v4l.org/rFIbk

Search value in array from comma separated value in PHP

I have following array
Array
(
[0] => Array
(
[data] => PHP
[attribs] => Array
(
)
[xml_base] =>
[xml_base_explicit] =>
[xml_lang] =>
)
[1] => Array
(
[data] => Wordpress
[attribs] => Array
(
)
[xml_base] =>
[xml_base_explicit] =>
[xml_lang] =>
)
)
one varialbe like $var = 'Php, Joomla';
I have tried following but not working
$key = in_multiarray('PHP', $array,"data");
function in_multiarray($elem, $array,$field)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom][$field] == $elem)
return true;
else
if(is_array($array[$bottom][$field]))
if(in_multiarray($elem, ($array[$bottom][$field])))
return true;
$bottom++;
}
return false;
}
so want to check if any value in $var is exists in array(case insensitive)
How can i do it without loop?
This should work for you:
(Put a few comments in the code the explain whats goning on)
<?php
//Array to search in
$array = array(
array(
"data" => "PHP",
"attribs" => array(),
"xml_base" => "",
"xml_base_explicit" => "",
"xml_lang" => ""
),
array(
"data" => "Wordpress",
"attribs" => array(),
"xml_base" => "",
"xml_base_explicit" => "",
"xml_lang" => "Joomla"
)
);
//Values to search
$var = "Php, Joomla";
//trim and strtolower all search values and put them in a array
$search = array_map(function($value) {
return trim(strtolower($value));
}, explode(",", $var));
//function to put all non array values into lowercase
function tolower($value) {
if(is_array($value))
return array_map("tolower", $value);
else
return strtolower($value);
}
//Search needle in haystack
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
//Search ever value in array
foreach($search as $value) {
if(in_array_r($value, array_map("tolower", array_values($array))))
echo $value . " found<br />";
}
?>
Output:
php found
joomla found
to my understanding , you are trying to pass the string ex : 'php' and the key : 'data' of the element .
so your key can hold a single value or an array .
$key = in_multiarray("php", $array,"data");
var_dump($key);
function in_multiarray($elem, $array,$field)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if(is_array($array[$bottom][$field]))
{
foreach($array[$bottom][$field] as $value)
{
if(strtolower(trim($value)) == strtolower(trim($elem)))
{
return true;
}
}
}
else if(strtolower(trim($array[$bottom][$field])) == strtolower(trim($elem)))
{
return true;
}
$bottom++;
}
return false;
}

PHP get array of search terms from string

Is there an easy way to parse a string for search terms including negative terms?
'this -that "the other thing" -"but not this" "-positive"'
would change to
array(
"positive" => array(
"this",
"the other thing",
"-positive"
),
"negative" => array(
"that",
"but not this"
)
)
so those terms could be used to search.
The code below will parse your query string and split it up into positive and negative search terms.
// parse the query string
$query = 'this -that "-that" "the other thing" -"but not this" ';
preg_match_all('/-*"[^"]+"|\S+/', $query, $matches);
// sort the terms
$terms = array(
'positive' => array(),
'negative' => array(),
);
foreach ($matches[0] as $match) {
if ('-' == $match[0]) {
$terms['negative'][] = trim(ltrim($match, '-'), '"');
} else {
$terms['positive'][] = trim($match, '"');
}
}
print_r($terms);
Output
Array
(
[positive] => Array
(
[0] => this
[1] => -that
[2] => the other thing
)
[negative] => Array
(
[0] => that
[1] => but not this
)
)
For those looking for the same thing I have created a gist for PHP and JavaScript
https://gist.github.com/UziTech/8877a79ebffe8b3de9a2
function getSearchTerms($search) {
$matches = null;
preg_match_all("/-?\"[^\"]+\"|-?'[^']+'|\S+/", $search, $matches);
// sort the terms
$terms = [
"positive" => [],
"negative" => []
];
foreach ($matches[0] as $i => $match) {
$negative = ("-" === $match[0]);
if ($negative) {
$match = substr($match, 1);
}
if (($match[0] === '"' && substr($match, -1) === '"') || ($match[0] === "'" && substr($match, -1) === "'")) {
$match = substr($match, 1, strlen($match) - 2);
}
if ($negative) {
$terms["negative"][] = $match;
} else {
$terms["positive"][] = $match;
}
}
return $terms;
}

how to convert a string with brackets to an array in php

I'm having a problem with this. I have a string that looks like this:
coilovers[strut_and_individual_components][complete_strut][][achse]
And i want to convert it to to array that looks like this:
[coilovers] => Array
(
[strut_and_individual_components] => Array
(
[complete_strut]=> Array
(
[1] => Array
(
[achse] => some_value
)
[2] => Array
(
[achse] => some_value
)
)
)
)
is it possible?
Here is a quick implementation of a parser that will attempt to parse this string:
$input = 'coilovers[strut_and_individual_components][complete_strut][][achse]';
$output = array();
$pointer = &$output;
while( ($index = strpos( $input, '[')) !== false) {
if( $index != 0) {
$key = substr( $input, 0, $index);
$pointer[$key] = array();
$pointer = &$pointer[$key];
$input = substr( $input, $index);
continue;
}
$end_index = strpos( $input, ']');
$array_key = substr( $input, $index + 1, $end_index - 1);
$pointer[$array_key] = array();
$pointer = &$pointer[$array_key];
$input = substr( $input, $end_index + 1);
}
print_r( $output);
Essentially, we are iterating the string to find matching [ and ] tags. When we do, we take the value within the brackets as $array_key and add that into the $output array. I use another variable $pointer by reference that is pointing to the original $output array, but as the iteration goes, $pointer points to the last element added to $output.
It produces:
Array
(
[coilovers] => Array
(
[strut_and_individual_components] => Array
(
[complete_strut] => Array
(
[] => Array
(
[achse] => Array
(
)
)
)
)
)
)
Note that I've left the implementation of [] (an empty array key) and setting the values in the last index (some_value) as an exercise to the user.
Well I've found an another answer for it and it looks like this:
private function format_form_data(array $form_values) {
$reformat_array = array();
$matches = array();
$result = null;
foreach($form_values as $value) {
preg_match_all("/\[(.*?)\]/", $value["name"], $matches);
$parsed_product_array = $this->parse_array($matches[1], $value["value"]);
$result = array_push($reformat_array, $parsed_product_array);
}
return $result;
}
private function parse_array(array $values, $value) {
$reformat = array();
$value_carrier_key = end($values);
foreach (array_reverse($values) as $arr) {
$set_value_carrier = array($arr => $reformat);
if($arr == $value_carrier_key) {
$set_value_carrier = array($arr => $value);
}
$reformat = empty($arr) ? array($reformat) : $set_value_carrier;
}
return $reformat;
}
where array $form_values is:
Array
(
[name] => '[coilovers][strut_and_individual_components][complete_strut][][achse]',
[value] => 'some_value'
)
No. If you evaluate the string you will get invalid PHP.
If you want to store a PHP Array as string and get it loaded back as PHP Array, have a look at serialize and unserialize functions.
Of course you can build an array from your string, but you'll have to write a parser.
The solution I propose:
function format_form_data(array $data) {
$matches = array();
$result = [];
foreach($data as $key => $value) {
preg_match_all("/\[(.*?)\]/", $key, $matches);
$matches = array_reverse($matches[1]);
$matches[] = substr( $key, 0, strpos($key, '['));;
foreach ($matches as $match) {
$value = [$match=>$value];
}
$result = array_replace_recursive($result, $value);
}
return $result;
}

PHP array - remove elements with keys that start with

Newbie question - I'm trying to remove elements with keys that start with 'not__'.
Its inside laravel project so I (can) use its array functions.
I'm trying to remove elements after the loop. This doesn't remove anything, i.e. it doesn't work:
function fixinput($arrinput)
{
$keystoremove = array();
foreach ($arrinput as $key => $value);
{
if (starts_with($key, 'not__'))
{
$keystoremove = array_add($keystoremove, '', $key);
}
}
$arrinput = array_except($arrinput, $keystoremove);
return $arrinput;
}
Note that it won't be the only task on array. I'll try that myself. :)
Thanks!
$filtered = array();
foreach ($array as $key => $value) {
if (strpos($key, 'not__') !== 0) {
$filtered[$key] = $value;
}
}
Using the array_filter function with the ARRAY_FILTER_USE_KEY flag looks to be the best/fastest option.
$arrinput = array_filter( $arrinput, function($key){
return strpos($key, 'not__') !== 0;
}, ARRAY_FILTER_USE_KEY );
The flag parameters weren't added until version 5.6.0 so for older versions of PHP a for loop would probably be the quickest option.
foreach ($arrinput as $key => $value) {
if(strpos($key, 'not__') === 0) {
unset($arrinput[$key]);
}
}
I would assume the following method is a lot slower but its just a different way of doing it.
$allowed_keys = array_filter( array_keys( $arrinput ), function($key){
return strpos($key, 'not__') !== 0;
} );
$arrinput = array_intersect_key($arrinput , array_flip( $allowed_keys ));
Function
if(!function_exists('array_remove_keys_beginning_with')){
function array_remove_keys_beginning_with( $array, $str ) {
if(defined('ARRAY_FILTER_USE_KEY')){
return array_filter( $array, function($key) use ($str) {
return strpos($key, $str) !== 0;
}, ARRAY_FILTER_USE_KEY );
}
foreach ($array as $key => $value) {
if(strpos($key, $str) === 0) {
unset($array[ $key ]);
}
}
return $array;
}
}
Some PHP-regex fu:
$array = array('not__foo' => 'some_data', 'bar' => 'some_data', 12 => 'some_data', 15 => 'some_data', 'not__taz' => 'some_data', 'hello' => 'some_data', 'not__world' => 'some_data', 'yeah' => 'some_data'); // Some data
$keys = array_keys($array); // Get the keys
$filter = preg_grep('#^not__#', $keys); // Get the keys starting with not__
$output = array_diff_key($array, array_flip($filter)); // Filter it
print_r($output); // Output
Output
Array
(
[bar] => some_data
[12] => some_data
[15] => some_data
[hello] => some_data
[yeah] => some_data
)
Try this...
function fixinput($arrinput)
{
$keystoremove = array();
foreach ($arrinput as $key => $value);
{
if (preg_match("#^not__#",$key))
{
$keystoremove = array_add($keystoremove, '', $key);
}
}
$arrinput = array_except($arrinput, $keystoremove);
return $arrinput;
}

Categories