Php consolidate number (zip codes) - php

I have a php array with zipcodes returned from a db query. Zip Codes are in German format so 5 digit long.
Example:
array ('90475', '90419', '90425', '90415', '90429', '90479', '90485');
I would like to consolidate the values to "ranges" with placeholder, like:
array ('90...', '904..', '9041.', '9042', '9047.');
//90485 is left out because there is only 1 match.
Edit / logic:
This is for an autosuggestion search. Trying to build a tree so users can search for entries that match any zipcode starting with 90 or 904, etc.. For the autocomplete to make sense I only want to provide the "9041." value if there is a minimum of two entries matching (90419 and 90415 in example). The zipcodes are always 5 digit long from 00000 - 99999.
Highly appreciate any help.
Thanks.

Here you are:
$length = 5;
$zip = array('90475', '90419', '90425', '90415', '90429', '90479', '90485');
$result = array();
for ($i = 2; $i <= $length - 1; $i++) {
$pass = array();
foreach ($zip as $val) {
$pass[substr($val, 0, $i)]++;
}
foreach ($pass as $key => $val) {
if ($val > 1) {
$result[] = $key.str_repeat('.', $length - $i);
}
}
}
sort($result);
var_dump($result);
This will return in $result an array:
array ('90...', '904..', '9041.', '9042', '9047.');
Every range, which is used only once will be ignored and not returned in $result array.

$myArray = array ('90475', '90419', '90425', '90415', '90429', '90479', '90485');
$consolidate = array();
foreach($myArray as $zip) {
for ($c = 2; $c < 5; ++$c) {
$key = substr($zip, 0, $c) . str_repeat('.',5 - $c);
$consolidate[$key] = (isset($consolidate[$key])) ? $consolidate[$key] + 1 : 1;
}
}
$consolidate = array_filter(
$consolidate,
function ($value) {
return $value > 1;
}
);
var_dump($consolidate);

Related

Return the number of all unique case-insensitive characters

I am trying create a function which returns the number of all unique case-insensitive
characters that occur >= $n times in a given string.
For example:
function getNumOfUniqueCharacters($str, $n) {
// ...
}
getNumOfUniqueCharacters('A1B2C3', 2); // 0
getNumOfUniqueCharacters('A1a1C1', 2);
// 2, because A and 1 both occur 2 or more times.
getNumOfUniqueCharacters('Alabama', 3); // 1
I did this:
function getNumOfUniqueCharacters($text)
{
$ret = 0;
$a = [];
$t = str_split(strtolower($text));
$l = count($t);
for ($i = 0; $i < $l; $i++) {
$c = $t[$i];
if (array_key_exists($c, $t)) {
if ($t[$c] === 1)
$ret += 1;
$t[$c] += 1;
} else {
$t[$c] = 1;
}
}
return $ret;
}
But it does not work so good, I need to add second argument $n.
How to add it correctly?
I hope I got your question right.
Here's my idea for this code:
<?php
$string = "A1B2C1A2b2b4b5";
function getNumOfUniqueCharacters($string, $n)
{
$occurrenceArray = array();
$text = str_split(strtolower($string));
//put each character in a keyValue array and count them
foreach($text as $character){
if(!array_key_exists($character, $occurrenceArray)) $occurrenceArray[$character] = 1;
else $occurrenceArray[$character]++;
}
//loop through keyValue array and remove everything that has value < $n
foreach($occurrenceArray as $key => $value)
{
if($value < $n) unset($occurrenceArray[$key]);
}
//return array
return $occurrenceArray;
}
print_r(getNumOfUniqueCharacters($string, 2));
This code right here will print the following:
Array (
[a] => 2
[1] => 2
[b] => 4
[2] => 3 )
Edit: If you need the count of how many characters repeat more than $n, you can simply replace the return with return count($occurrenceArray);
This task is pretty easy, if you use array functions of PHP:
function getNumOfUniqueCharacters(string $string = '', int $n = 1): int {
// Split the string by character and count the occurences of all values
$counted = array_count_values(mb_str_split(mb_strtolower($str)));
// Discard everything, that is does not match the $n parameter
$counted = array_filter($counted, function($a) use($n) {
return $a >= $n;
});
// Return the length of the remaining array
return count($counted);
}
Also note, that you may use mb_* functions, so your code will work with multibyte characters.
I have written you a function with a lot of comments to explain the thought process,
function getNumOfUniqueCharacters($string, $n = null) {
// Map all case-insensitive characters to an array
$map = str_split(strtolower($string), 1);
// Character registry
$reg = array_count_values($map);
// Filter out single occurances
$reg = array_filter($reg, function($v){return $v > 1;});
// Filter out less than $n occurances (if $n is not null)
if (null !== $n) {
$reg = array_filter($reg, function($v)use($n){return $v >= $n;});
}
// Return the number duplicate occurances (or more than n occurances)
return count($reg);
}
Usage:
echo getNumOfUniqueCharacters('A1B2C3', 2) . PHP_EOL;
echo getNumOfUniqueCharacters('A1a1C1', 2) . PHP_EOL;
echo getNumOfUniqueCharacters('Alabama', 3) . PHP_EOL;
echo getNumOfUniqueCharacters('Mississippi') . PHP_EOL;
Output:
0
2
1
3

Algorithm for exclude combinations with unique value using php

The algoritham i'm trying different combinations of values will able to give my exact or approx output sum of values
I have attached image for the detail explanation , I have created column total as sum of each row value and finally I have sum all the total value, the whole total sum value is to be my expected output value.
So I'm trying to take a combination of each row sum and like to get total sum value
My algorithm i have searched in google below
function extractList($array, &$list, $temp = array()) {
if (count($temp) > 0 && ! in_array($temp, $list))
$list[] = $temp;
for($i = 0; $i < sizeof($array); $i ++) {
$copy = $array;
$elem = array_splice($copy, $i, 1);
if (sizeof($copy) > 0) {
$add = array_merge($temp, array($elem[0]));
sort($add);
extractList($copy, $list, $add);
} else {
$add = array_merge($temp, array($elem[0]));
sort($add);
if (! in_array($temp, $list)) {
$list[] = $add;
}
}
}
}
echo "<pre>";
$sum = 32 ; //SUM
$array = array(5.14327,5.72355,5.91794,4.8209,8.69933,4.12977,4.12977,2.92791,2.36829,2.21819,1.33759,1.72278,1.72278,0.589,1.06405,0.6387,0.6387,1.68995,2.51669,3.97842,2.38058,2.17175,4.88264,5.84811,6.14215);
$list = array();
# Extract All Unique Conbinations
extractList($array, $list);
#Filter By SUM = $sum
$list = array_filter($list,function($var) use ($sum) { return(array_sum($var) == $sum);});
#Return Output
print_r($list);
Attached Image here
You need to decide how you determine approximate equality. A percentage? Or an absolute amount? That's what you need in your filter lambda function.
// outside lambda
$error = $sum * 5 / 100;// 5%, or
$error = 0.02;// an absolute
...
// inside lambda
return abs(array_sum($var) - $sum) <= $error;

All combinations of r elements from given array php

Given an array such as the following
$array = ('1', '2', '3', '4', '5', '6', '7');
I'm looking for a method to generate all possible combinations, with a minimum number of elements required in each combination r. (eg if r = 5 then it will return all possible combinations containing at least 5 elements)
Combinations of k out of n items can be defined recursively using the following function:
function combinationsOf($k, $xs){
if ($k === 0)
return array(array());
if (count($xs) === 0)
return array();
$x = $xs[0];
$xs1 = array_slice($xs,1,count($xs)-1);
$res1 = combinationsOf($k-1,$xs1);
for ($i = 0; $i < count($res1); $i++) {
array_splice($res1[$i], 0, 0, $x);
}
$res2 = combinationsOf($k,$xs1);
return array_merge($res1, $res2);
}
The above is based on the recursive definition that to choose k out n elements, one can fix an element x in the list, and there are C(k-1, xs\{x}) combinations that contain x (i.e. res1), and C(k,xs\{xs}) combinations that do not contain x (i.e. res2 in code).
Full example:
$array = array('1', '2', '3', '4', '5', '6', '7');
function combinationsOf($k, $xs){
if ($k === 0)
return array(array());
if (count($xs) === 0)
return array();
$x = $xs[0];
$xs1 = array_slice($xs,1,count($xs)-1);
$res1 = combinationsOf($k-1,$xs1);
for ($i = 0; $i < count($res1); $i++) {
array_splice($res1[$i], 0, 0, $x);
}
$res2 = combinationsOf($k,$xs1);
return array_merge($res1, $res2);
}
print_r ($array);
print_r(combinationsOf(5,$array));
//print_r(combinationsOf(5,$array)+combinationsOf(6,$array)+combinationsOf(7,$array));
A combination can be expressed as
nCr = n! / (r! - (n - r)!)
First, we determine $n as the number of elements in the array. And $r is the minimum number of elements in each combination.
$a = ['1', '2', '3', '4', '5', '6', '7']; // the array of elements we are interested in
// Determine the `n` and `r` in nCr = n! / (r! * (n-r)!)
$r = 5;
$n = count($a);
Next, we determine $max as the maximum number that can be represented by $n binary digits. That is, if $n = 3, then $max = (111)2 = 7. To do this, we first create a empty string $maxBinary and add $n number of 1s to it. We then convert it to decimal, and store it in $max.
$maxBinary = "";
for ($i = 0; $i < $n; $i++)
{
$maxBinary .= "1";
}
$max = bindec($maxBinary); // convert it into a decimal value, so that we can use it in the following for loop
Then, we list out every binary number from 0 to $max and store those that have more than $r number of 1s in them.
$allBinary = array(); // the array of binary numbers
for ($i = 0; $i <= $max; $i++)
{
if (substr_count(decbin($i), "1") >= $r) // we count the number of ones to determine if they are >= $r
{
// we make the length of the binary numbers equal to the number of elements in the array,
// so that it is easy to select elements from the array, based on which of the digits are 1.
// we do this by padding zeros to the left.
$temp = str_pad(decbin($i), $n, "0", STR_PAD_LEFT);
$allBinary[] = $temp;
}
}
Then, we use the same trick as above to select elements for our combination. I believe the comments explain enough.
$combs = array(); // the array for all the combinations.
$row = array(); // the array of binary digits in one element of the $allBinary array.
foreach ($allBinary as $key => $one)
{
$combs[$key] = "";
$row = str_split($one); // we store the digits of the binary number individually
foreach ($row as $indx => $digit)
{
if ($digit == '1') // if the digit is 1, then the corresponding element in the array is part of this combination.
{
$combs[$key] .= $a[$indx]; // add the array element at the corresponding index to the combination
}
}
}
And that is it. You are done!
Now if you have something like
echo count($combs);
then it would give you 29.
Additional notes:
I read up on this only after seeing your question, and as a newcomer, I found these useful:
Wikipedia - http://en.wikipedia.org/wiki/Combination
Php recursion to get all possibilities of strings
Algorithm to return all combinations of k elements from n
Also, here are some quick links to the docs, that should help people who see this in the future:
http://php.net/manual/en/function.decbin.php
http://php.net/manual/en/function.bindec.php
http://php.net/manual/en/function.str-pad.php
function arrToBit(Array $element) {
$bit = '';
foreach ($element as $e) {
$bit .= '1';
}
$length = count($element);
$num = bindec($bit);
$back = [];
while ($num) {
$back[] = str_pad(decbin($num), $length, '0', STR_PAD_LEFT);
$num--;
}
//$back[] = str_pad(decbin(0), $length, '0', STR_PAD_LEFT);
return $back;
}
function bitToArr(Array $element, $bit) {
$num = count($element);
$back = [];
for ($i = 0; $i < $num; $i++) {
if (substr($bit, $i, 1) == '1') {
$back[] = $element[$i];
}
}
return $back;
}
$tags = ['a', 'b', 'c'];
$bits = arrToBit($tags);
$combination = [];
foreach ($bits as $b) {
$combination[] = bitToArr($tags, $b);
}
var_dump($combination);
$arr = array(1,2,3,4,5,6);
$check_value =[];
$all_values = [];
CONT:
$result = $check_value;
shuffle($arr);
$check_value = array_slice($arr,0,3);
if(count($check_value) == 3 && serialize($check_value) !== serialize($result)){
$result = $check_value;
array_push($all_values,$result);
goto CONT;
}
print_r($all_values);

How to extract adjacent pair of words in associative array in php?

I have an associative array in PHP like this:
$weight["a"]=1;
$weight["b"]=4;
$weight["c"]=5;
$weight["d"]=9;
Here I want to calculate pair-wise difference between consecutive array elements, e.g.,
"b-a" = 3
"c-b" = 1
"d-c" = 4
How should this be computed?
Try this:
$i = 0;
foreach ($weight AS $curr) {
if ($i > 0) {
echo '"'.array_keys($weight)[$i].'-'.array_keys($weight)[$i-1].'" = '.($curr-$prev)."<br />";
}
$i++;
$prev = $curr;
}
Store keys on a temporary array where keys are integers on which you can easily get the next key, and use it to parse your main array.
$tmp_array = array();
foreach ($weight as $key => $val) {
$tmp_array[] = $key;
}
$array_length = count($tmp_array);
for ($i = 0; i < array_length - 2; ++$i) {
echo $weight[$tmp_array[$i+1]], '-', $weight[$tmp_array[$i]], ' = ', ($weight[$tmp_array[$i+1]] - $weight[$tmp_array[$i]], PHP_EOL;
}

PHP: Efficiently Search through Collections

I have collections of numbers (arbitrary order) to store.
psuedocode:
id_a:[3,5,7,11]
id_x:[3,5,10,21]
id_b:[12,24,25,26]
etc.
I need to be able to search through all the collections and return the group_IDs.
For example, if I look up 5, I should get back ['id_a','id_x']. I want to do this efficiently with some sort of mapping, not by looping through all numbers of all collections. I also want to be able to map directly to each key and get back the collection (e.g., 'id_x' returns [3,5,10,21]) ; again I prefer this be done efficiently without looping through the keys.
edit:
I could use the numbers as the keys and efficiently get back 'id_'. Or, I could go the other way and use 'id_' as keys and efficiently get back the array of numbers. However, I want to be able to go efficiently in both directions. I guess I could maintain two arrays, but that seems messy.
Your examples all show the array values in sorted order. If they are always in sorted order, then you can use a binary search to find known values. This code:
function binarySearch($needle, array $haystack) {
$high = count($haystack) - 1;
$low = 0;
$mid = false;
while ($high >= $low) {
$mid = ($high + $low) >> 1;
$t = $needle - $haystack[$mid];
if ($t < 0) {
$high = $mid - 1;
} elseif ($t > 0) {
$low = $mid + 1;
} else {
return $mid;
}
}
return $mid;
}
function searchArrays($needle) {
static $id_a = array(3,5,7,11);
static $id_x = array(3,5,10,21);
static $id_b = array(12,24,25,26);
static $arrayNames = array('id_a', 'id_x', 'id_b');
$rv = array();
foreach ($arrayNames as $arrayName) {
$array = $$arrayName;
$index = binarySearch($needle, $array);
if ($array[$index] == $needle) {
$rv[] = $arrayName;
}
}
return $rv;
}
$needles = range(3,8);
foreach ($needles as $needle) {
$result = searchArrays($needle);
printf("searchArrays(%s)=%s\n", $needle, join(', ', $result));
}
will output the following:
searchArrays(3)=id_a, id_x
searchArrays(4)=
searchArrays(5)=id_a, id_x
searchArrays(6)=
searchArrays(7)=id_a
searchArrays(8)=

Categories