Hi,

I have a string that can look a little different from time to time.

String Example 1: ((823584X80X998.NAOK == "1"))
String Example 2: ((823584X80X1001.NAOK == "1" or 823584X80X1001.NAOK == "2" or 823584X80X1001.NAOK == "3"))

And I have this array with matching key (i've shortened the array for readability)

(
    [823584X80X998.NAOK] => Array
        (
            [question_properties] => Array
                (
                    [qid] => 998
                    [name] => 'F8'
                )
        )
    [823584X80X1001.NAOK] => Array
        (
            [question_properties] => Array
                (
                    [qid] => 1001
                    [name] => 'F10'
                )
        )
)

so what I want to be able to do is to echo the string but replace the matching key with the name property of the array

So the result would look like this:

String Example 1: ((F8 == "1"))
String Example 2: ((F10 == "1" or F10 == "2" or F10 == "3"))

Any thoughts?

Cheers
/Adam

Just to clarify - the string can actualy be one of the values below:

$stringExample = '((823584X80X998.NAOK == "1"))';
$stringExample = '((823584X80X1001.NAOK == "1" or 823584X80X1001.NAOK == "2" or 823584X80X1001.NAOK == "3"))';

If that is true, you have to:
- get rid of all the parentheses
- explode by OR operators
- explode each by == operators
- save values on the right of the == operators
- figure out the value of the key
- find that key in the array and get the name value
- assemble and echo the thing

Please confirm if I understood the question correctly.

The basic structure of the string is

  1. startbrackets: ((
  2. Question id: 823584X80X1001.NAOK
  3. one of many comparison operator: != or == or <= etc
  4. value "1" (could be a letter as well)
  5. either end brackets )) or another condition joined with either "or""and" and then end brackets.

Hopefully its' clearer now... :)
Thanks for taking time looking att my problem!

I hope this is what you want (see comments in the code):

// test data
$mainArray = array(
    '823584X80X998.NAOK' => array('question_properties' => array('qid' => 998,  'name' => 'F8')),
    '823584X80X1001.NAOK' => array('question_properties' => array('qid' => 1001, 'name' => 'F10'))
);
// $string = '((823584X80X998.NAOK == "1"))';
$string = '((823584X80X1001.NAOK == "1" or 823584X80X1001.NAOK == "2" or 823584X80X1001.NAOK == "3"))';

// get rid of the (( and ))
$string = str_replace(array('(', ')'), '', $string);
// explode if there are any ORs
$tempArray1 = explode(' or ', $string);
// save values (1, 2, 3)
$savedValues = array();
foreach($tempArray1 as $val1) {
    $tempArray2 = explode('==', $val1);
    // this will be the key for searching in the main array
    $searchKey = trim($tempArray2[0]);
    // ad a value to the saved values array
    $savedValues[] = $tempArray2[1];
}
// to check if OR has to be echoed
$savedValuesCount = count($savedValues);
if(array_key_exists($searchKey, $mainArray)) {
    echo "((";
    foreach($savedValues as $key2 => $savedVal) {
        // echo replacement
        echo $mainArray[$searchKey]['question_properties']['name'] . '==' . $savedVal . '';
        // echo OR if needed
        if($key2 < $savedValuesCount -1) {
            echo ' or ';
        }
    }
    echo '))';
} else {
    // in case key does not exist
    echo "Search key $searchKey does not exist in the main array";
}

Just noticed. The above example will work only if you have OR operators. To take into account other operators the explode will not work. A function can be prepared for that.

this will also work as an alternative to str_replace

$string = trim($string,'(())');
Member Avatar for diafol

How about a simple preg match and replace? About 9 lines of code should do it?

function change_keys($query, $questionArray, $patternPre, $pattern, $patternPost)
{
    $pattern = $patternPre . $pattern . $patternPost;
    preg_match_all($pattern, $query, $r, PREG_SET_ORDER);
    $searchPatterns = [];
    $replacements = [];
    foreach($r as $v)
    {
        $key = $v[1];
        $searchPatterns[] = $patternPre . $key . $patternPost;
        $replacements[] = $questionArray[$key]['question_properties']['name'];
    }
    return preg_replace($searchPatterns, $replacements, $query);
}

Usage:

$myQuery = '((823584X80X1001.NAOK == "1" or 823584X80X1001.NAOK == "2" or 823584X80X1001.NAOK == "3"))';

$myQuestionData = [
    "823584X80X998.NAOK" => ["question_properties" => ["qid" => 998,  "name" => "F8"]],
    "823584X80X1001.NAOK" => ["question_properties" => ["qid" => 1001,  "name" => "F10"]]
];

$patternPre = '#\b';
$patternPost = '\b#';
$pattern = '([0-9X]*.NAOK)';

echo change_keys($myQuery, $myQuestionData, $patternPre, $pattern, $patternPost);

echo "<br />";

$stringExample = '((823584X80X998.NAOK == "1"))';

echo change_keys($stringExample, $myQuestionData, $patternPre, $pattern, $patternPost);

OUTPUTS:

((F10 == "1" or F10 == "2" or F10 == "3"))
((F8 == "1"))

BTW: the capture group 'pattern' is assumed to be made of digits and X's of variable length, followed by a period and the string NAOK. If theese 'keys' can vary, then the pattern needs to reflect that variability.

commented: Nice +11
Member Avatar for diafol

Looked back on that and thought 'urgh' - too specific. Tried to make it more generic, so included an array parsing transversing thingymabob:

<?php
//CREATES NEW FLAT KEY-VALUE ARRAY FROM SUPPLIED $dataArray
function goto_position($dataArray, $valuePosition)
{
    $output = [];
    $origKeys = array_keys($dataArray);
    $keys = explode('|', $valuePosition);

    foreach($dataArray as $element)
    {
        $array = $element;
        foreach ($keys as $key)
        {
            $array = $array[$key];
        }
        $output[] = $array;
    }
    return array_combine($origKeys, $output);
}

//REPLACES SUBSTRINGS 'KEYS' WITH VALUES
function change_keys($string, $dataArray, $valuePosition, $preCapture, $captureGroup, $postCapture)
{
    $pattern = '#' . $preCapture . '(' . $captureGroup . ')' . $postCapture . '#';
    preg_match_all($pattern, $string, $matches, PREG_SET_ORDER);
    $searchPatterns = [];
    $replacements = [];
    $newKeys = goto_position($dataArray, $valuePosition);
    foreach($matches as $v)
    {
        $key = $v[1];
        $searchPatterns[] = '#' . $preCapture  . '(' . $key . ')' .  $postCapture . '#';
        $replacements[] = $newKeys[$key];
    }
    return preg_replace($searchPatterns, $replacements, $string);
}

Usage:

//The STRING SUPPLIED TO THE FUNCTION
$myQuery = '((823584X80X1001.NAOK == "1" or 823584X80X1001.NAOK == "2" or 823584X80X1001.NAOK == "3"))';

//THE 'DATA'
$dataArray = [
    "823584X80X998.NAOK" => ["question_properties" => ["qid" => 998,  "name" => "F8"]],
    "823584X80X1001.NAOK" => ["question_properties" => ["qid" => 1001,  "name" => "F10"]]
];

//THE 'POSITION' OF THE VALUES OF INTEREST - ARRAY LEVELS SEPARATED BY PIPE - |
$valuePosition = 'question_properties|name';

//THE REGEX BITS
$c1 = '\b'; //before the capture group - without delimiter
$c2 = '[0-9X]*.NAOK'; //the actual capture group - without brackets
$c3 = '\b'; //after the capture group - without delimiter

echo change_keys( $myQuery, $dataArray, $valuePosition, $c1, $c2, $c3 );

Seems to work, but not tested extensively. Adds a bit of flexibility, e.g. swap weird key for 'qid' instead of 'name', just by changing:

 $valuePosition = 'question_properties|qid';

wow!! Thanks a bunch for som really good solutions!! I'm going with Diafols suggestion, really elegant work!

Take care
/Adam

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.