Reading your file
To start with, opening the file... file()
is the easiest method to read a file into an array as it is performed with one line.
Drawbacks:
-
file()
can be slow for larger files, as it needs to read the entire file into an array before you can use it
Alternatively, use the standard file open structure using something like fgets()
to read it line by line.
Drawbacks:
- more lines of code required
Let's use file()
as an example:
$lines = file('postcodes.txt');
Getting the array structure
The first part of your question is how to get the array structure you want, which is the suburb name as the array key and all the post codes as the values. There are plenty of ways to do this - here's a simple example using a foreach:
// Define an empty array to start with
$postcodes = array();
// Loop each line
foreach($lines as $line) {
// Split the line by the comma and define the variables with each part
// mapping trim to the array to remove any whitespace on either end
list($postcode, $suburb) = array_map('trim', explode(',', $line));
// Check the array key exists in post codes
if(!array_key_exists($suburb, $postcodes)) {
// If not, define it to start with
$postcodes[$suburb] = array();
}
// Check if the postcode is already in the array
if(in_array($postcode, $postcodes[$suburb])) {
// Skip this postcode, it's already where it should be
continue;
}
// Add the postcode to it
$postcodes[$suburb][] = $postcode;
}
Docs: array_map()
, array_key_exists()
, in_array()
, explode()
, foreach
, continue
An output of the resulting array would yield something like this:
Array
(
[MELBOURNE] => Array
(
[0] => 3000
[1] => 3001
)
[EAST MELBOURNE] => Array
(
[0] => 3002
)
[WEST MELBOURNE] => Array
(
[0] => 3003
)
)
Searching the array
Searching is a kettle of fish, and there are many things to consider. Do you want to return a case sensitive result, case insensitive, partial results, multiple results etc?
Here are some options and what you should use for them:
- Exact match (single):
array_keys($postcodes, 'suburb name')
- Exact match (multiple): wouldn't happen as you're using array keys (unique by definition)
- Partial match (single): a loop,
strstr()
(case sensitive) or stristr()
(case insensitive) matching the key and the search term and killing the loop if it is found
- Partial match (multiple): same as above, but don't kill the loop if it's found, instead add to an array of matched results and return that
Here's an example function to return all partially matches results from the array:
function search($postcodes, $search_term) {
// Define empty array for matches
$matches = array();
// Trim the search string to remove whitespace from either end
$search_term = trim($search_term);
// Loop through postcodes
foreach($postcodes as $suburb => $post_codes) {
// Case insensitive comparison
if(stristr($suburb, $search_term)) {
// It matches! Add entire result to return array
$matches[$suburb] = $post_codes;
}
}
// Return result
return $matches;
}
Example use:
print_r($search($postcodes, 'melbourne'));
print_r($search($postcodes, 'east'));
Array
(
[MELBOURNE] => Array
(
[0] => 3000
[1] => 3001
)
[EAST MELBOURNE] => Array
(
[0] => 3002
)
[WEST MELBOURNE] => Array
(
[0] => 3003
)
)
Array
(
[EAST MELBOURNE] => Array
(
[0] => 3002
)
)
Looking forward, you might also want to match any of the search terms passed in as a string, e.g. "east west" to match both east and west Melbourne. In this case you'll need to explode the search string to spaces, and perform a search on each term. You'll need to ensure to only return unique values here. Here's an example of a function that would do that:
function search_multi($postcodes, $search_term) {
// Define empty array for matches
$matches = array();
// Trim the search string
$search_term = trim($search_term);
// Get all search terms
$search_terms = explode(' ', $search_term);
// Loop through search terms
foreach($search_terms as $term) {
// Loop through postcodes
foreach($postcodes as $suburb => $post_codes) {
// First, check that this result hasn't already been found! (unique)
if(array_key_exists($suburb, $matches)) {
// It's already been found, skip this one...
continue;
}
// Case insensitive comparison
if(stristr($suburb, $term)) {
// It matches! Add entire result to return array
$matches[$suburb] = $post_codes;
}
}
}
// Return result
return $matches;
}
And given you search for "east west", the result would be:
Array
(
[EAST MELBOURNE] => Array
(
[0] => 3002
)
[WEST MELBOURNE] => Array
(
[0] => 3003
)
)
Conclusion
This kind of data structure would be best to be stored in a database if it's going to be used more than once, but to parse a text/CSV file this is how you'd approach it. Hope this helps.