简体   繁体   中英

Display multiple associated array values in lists dynamically

This is a difficult one to know what to search for, but I've done the homework and despite how common I thought this would be, I could not find anything so I hope I can explain it ok:

I am processing a CSV file into arrays using PHP fgetcsv , and so I have arrays like this:

[0] => Array
    (
        [0] => Australia
        [1] =>  Vic
        [2] =>  Swin
        [3] =>  Tech
    )

[1] => Array
    (
        [0] => Australia
        [1] =>  Vic
        [2] =>  Monash
        [3] =>  Psych
    )

[2] => Array
    (
        [0] => Australia
        [1] =>  NSW
        [2] =>  Monash
        [3] =>  Building
    )

I would like to build a set of lists that dynamically update based on any selection of any of the elements in the array. Ie, if you select value "Vic", it should pull out all the elements with "Vic" in item [1] - in this case would return array 0 and 1 and therefore display lists like this:

Country | State | Uni | Course
-------------------------------
Aus      Vic     Swin   Tech
Aus      Vic     Monash Psych

You should then be able to select "Uni=Swin" and get:

Country | State | Uni | Course
-------------------------------
Aus      Vic     Swin   Tech

To be honest, I'm not even sure where to start in regard to architecting this correctly for efficiency - ie, do I need to change the arrays to create associative keys that can be pulled out easily ? If so, do I need a new array for each key since I want to be able to filter them based on any of the Country, State, Uni, Course fields ?

Hope that's ok, its a little broad, but i'm sure its been done, I'm just struggling to find a nice way to structure it - I'm sure I could do it easily if I just wanted to start with the one filter, eg, Country, but I would like to make it as flexible as possible.

I'm sure there is a more fancy way of doing it, but this is readable and gets the job done.

$array = [

    [ 'apple', 'orange', 'banana'],
    [ 'apple', 'strawberry', 'banana']

];

function getRowsThroughElementValue($value, array $array) {
    $matched = [];

    foreach($array as $row) {
        if (!is_array($row)) {
            continue; // Not an array
        }

        if (in_array($value, $row)) {
            $matched[] = $row;
        }
    }

    return $matched;
}

var_dump(getRowsThroughElementValue('apple', $array));

Essentially, the code loops through the first array, and then checks for the specified value in the whole row array. If it exists, add it to the matched array.

You can just replace 'Vic' with your search string

<?php
$haystack = Array(Array('Australia','Vic','Swin','Tech'),Array('Australia','Vic','Monash','Psych'),Array('Australia','NSW','Monash','Building'));
function recursive_array_search($needle,$haystack) {
    foreach($haystack as $key=>$value) {
        $current_key=$key;
        if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
            return $current_key;
        }
    }
    return false;
}


for($i<0;$i<count($haystack);$i++)
{
    $final_array[] = $haystack[recursive_array_search('Vic',$haystack)];    
}

echo "<pre>";print_r($final_array); 
?>
class data{

    const COUNTRY = 0;
    const STATE = 1;
    const UNI = 2;
    const COURSE = 3;

    private $csv;

    function __construct($file){

        $this->csv = fgetcsv($file);

        //$this->csv[] = array('Australia', 'Vic', 'Swin', 'Tech');
        //$this->csv[] = array('Australia', 'Vic', 'Monash', 'Psych');
        //$this->csv[] = array('Australia', 'NSW', 'Monash', 'Building');

    } 

    public function getData($type, $match) {

        $return = array();

        if (is_array($this->csv)){

            foreach ($this->csv as $key => $row){

                if (isset($row[$type])){

                    if ($row[$type] == $match){

                        $return[] = $row;

                    }

                }

            }

        }   

        return $return;

    }   

}

$data = new data('path to your file');

$rows = $data->getData($data::STATE, 'Vic');

print_r($rows);

$rows = $data->getData($data::UNI, 'Swin');

print_r($rows);

To do a lot of lookups while keeping it all in arrays, one approach is to build index arrays. These are just simple arrays keyed on a certain lookup field, with the value being a list of all the elements in your main array which match that lookup. You would have an index array for each field that you might need to do a lookup against.

So, you could build the uni index like this:

$uni_index = array();
foreach($main_data as $key => $value) {
    $uni = $value[2];
    if(!isset($uni_index[$uni])) {
        $uni_index[$uni] = array();
    }
    $uni_index[$uni][] = $key;
}

This will give you an array like this:

Array ( 
    [Swin] => Array ( [0] => 0 ) 
    [Monash] => Array ( [0] => 1 [1] => 2 ) 
)

So if you did a lookup $uni_index['Swin'], you will get an array telling you that there is one matching result, at index 0. So $main_data[0] has all the matching data.

This allows you to do much quicker lookups. because you don't need loops after the index is set up. You're always using array keys. It can be a good approach if you want to keep everything in arrays, and will be doing a lot of lookups.

Other solutions may make sense depending on your use-case. If you will be doing occasional imports and keeping the data long-term, putting it in a database is likely to be the way to go. If you're doing a one time run with few lookups, simply looping over the array might be the best approach. But if you want to do a large number of lookups on your data in memory, then building indexes like this will make things much more efficient.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM