Viewed   52 times

I've got a multidimensional associative array which includes an elements like

$data["status"]
$data["response"]["url"]
$data["entry"]["0"]["text"]

I've got a strings like:

$string = 'data["status"]';
$string = 'data["response"]["url"]';
$string = 'data["entry"]["0"]["text"]';

How can I convert the strings into a variable to access the proper array element? This method will need to work across any array at any of the dimensions.

 Answers

1

Quick and dirty:

echo eval('return $'. $string . ';');

Of course the input string would need to be be sanitized first.

If you don't like quick and dirty... then this will work too and it doesn't require eval which makes even me cringe.

It does, however, make assumptions about the string format:

<?php
$data['response'] = array(
    'url' => 'http://www.testing.com'
);

function extract_data($string) {
    global $data;

    $found_matches = preg_match_all('/["([a-z]+)"]/', $string, $matches);
    if (!$found_matches) {
            return null;
    }

    $current_data = $data;
    foreach ($matches[1] as $name) {
            if (key_exists($name, $current_data)) {
                    $current_data = $current_data[$name];
            } else {
                    return null;
            }
    }

    return $current_data;
} 

echo extract_data('data["response"]["url"]');
?>
Monday, November 28, 2022
5

Here is a way to do the job:

$in = array(
"%@-H-e-l-l-o-7-9#$%",
"Hi$73",
"????????!",
"!",
"",
"?55?W",
'$abc$$$',
"?????_",
"34.5",
'#_!',
);

foreach($in as $elem) {
    preg_match('/^([^pLpN]*)((?=[pLpN]|$)[^_]*(?<=[pLpN])|^)?([^pLpN]*)$/u', $elem, $m);
    printf("'%15s'%s'%10s't%s'%10s't%s'%10s'%s", "$elem","=> (1): ",$m[1],"(2): ",$m[2], "(3): ",$m[3],"n");

}

Where:

  • pL stands for any letter in any language
  • pN stands for any number in any language

Output:

'%@-H-e-l-l-o-7-9#$%'=> (1): '       %@-'   (2): 'H-e-l-l-o-7-9'    (3): '       #$%'
'          Hi$73'=> (1): '          '   (2): '     Hi$73'   (3): '          '
'????????!'=> (1): '          ' (2): '????????' (3): '         !'
'              !'=> (1): '         !'   (2): '          '   (3): '          '
'               '=> (1): '          '   (2): '          '   (3): '          '
'        ?55?W'=> (1): '          ' (2): '   ?55?W' (3): '          '
'        $abc$$$'=> (1): '         $'   (2): '       abc'   (3): '       $$$'
'    ?????_'=> (1): '          '    (2): '?????'    (3): '         _'
'           34.5'=> (1): '          '   (2): '      34.5'   (3): '          '
'            #_!'=> (1): '       #_!'   (2): '          '   (3): '          '
Friday, September 16, 2022
 
1

Based on your given code, we can reverse-engineer the structure of $arr2 to (assuming R, G and B are integer from 0 to 255):

$arr2 = array(
   0 => array(
      0 => array(
        "R" => 128,
        "G" => 64,
        "B" => 255
      ),
      1 => array(
        ...
      ) 
   )
);

Given that your $SIZE is set to 256, you will have a total of 256*256=65536 arrays further containing arrays with key-values for R, G and B, resulting in total of 256*256*3=196608 integers in 3 levels of hierarchy. No surprise your code is slow!

I think the best strategy here is to try to reduce the total number of items in your array.

Given that instead of encoding single cells as "R, G, B" triples, you could encode all values in a single integer. Such as instead of:

0 => array( "R" => $r, "G" => $g, "B" => $b )

Given that 0<=r,g,b<=255, you could encode $arr2 as:

0 => ($r<<16 + $g<<8 + $b);

Now of course you need to unpack the color value inside your loop as well. This can be achieved by:

$col = $arr2[$y][$x];
$col_b = ($col&255);
$col_g = ($col>>8)&255;
$col_r = ($col>>16)&255;
$r .= $col_r.":";
$g .= $col_g.":";
$b .= $col_b.":";

This modification alone would cut one level of hierarchy from your array completely.

While running your original code with $SIZE=256, my average execution speed in my settings was 0.30 secs. With the given refactoring, I was able to reduce this to 0.10 secs cutting your calculation time to 1/3 of the original.

You will still have a lot of work to do if you wish to improve the performance, but I hope this gives you an idea on how you could proceed.

Monday, August 1, 2022
 
drtrd
 
3

According to Python, an identifier is a letter or underscore, followed by an unlimited string of letters, numbers, and underscores:

import re

def clean(s):

   # Remove invalid characters
   s = re.sub('[^0-9a-zA-Z_]', '', s)

   # Remove leading characters until we find a letter or underscore
   s = re.sub('^[^a-zA-Z_]+', '', s)

   return s

Use like this:

>>> clean(' 32v2 g #Gmw845h$W b53wi ')
'v2gGmw845hWb53wi'
Friday, November 18, 2022
4

Updated for Swift 3.0

You need two date formatters - one to make sense of your input string and convert to a NSDate, and a different formatter to create the output string

    let myDateString = "2016-01-01 04:31:32.0"

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.A"
    let myDate = dateFormatter.date(from: myDateString)!

    dateFormatter.dateFormat = "MMM dd, YYYY"
    let somedateString = dateFormatter.string(from: myDate)

I have updated this answer to change the date formatter from YYYY to yyyy. In most cases, there will be no difference between the two, but YYYY may treat the first few days of the year as being part of the last complete week of the previous year.

The Apple developer guides explain it like this.

A common mistake is to use YYYY. yyyy specifies the calendar year whereas YYYY specifies the year (of “Week of Year”), used in the ISO year-week calendar. In most cases, yyyy and YYYY yield the same number, however they may be different. Typically you should use the calendar year.

Wednesday, August 17, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :