This is more of a conceptual question concerning the built in functionality of PHP and arrays. I was wondering if there is any way to do the following:
You have an array $a and this array contains 5 elements (0-4) for the purpose of this example.
Is there any way to make a new array, which would contain the following:
$b[0] = $a[0];
$b[1] = $a[0] + $a[1];
$b[2] = $a[0] + $a[1] + $a[2];
$b[3] = $a[0] + $a[1] + $a[2] + $a[3];
$b[4] = $a[0] + $a[1] + $a[2] + $a[3] + $a[4];
etc..
I imagine an example of it's use would be bread crumbs on a website, where you could click on any directory of a given link like /dir1/dir2/dir3/dir4
Is there anything built into PHP that can handle building up an array in this fashion? Or examples of a function which handles this? Or even a better way to go about this.
Thanks!
EDIT: Here is the final solution via the help of you guys! This will build the link, and create the proper link for each directory/element.
//$a is our array
$max = count($a);
foreach (range(1,$max) as $count) {
$b[] = implode("/", array_slice($a, 0, $count));
}
foreach($b as $c) {
$x = explode('/' , $c);
$y = array_pop($x);
echo "<a href='$c'>".$y."</a>"."/";
}
If you just want the five combinations as in your example then:
foreach (range(1,5) as $count) {
$b[] = implode("/", array_slice($a, 0, $count));
}
You'd be best with a recursive function in that case.
$arr = array('dir1', 'dir2', 'dir3', 'dir4', 'dir5');
function breadcrumbs($a)
{
// Remove first value
$first = array_shift($a);
// Loop through other values
foreach ($a as $key => $value)
{
// Add first to remaining values
$a[$key] = $first . '/' . $value;
}
// Return array
return array($first) + breadcrumbs($a);
}
Untested, but should work. It will make each sequential value contain the values before it in the array.
$b = array();
for($i=0;$i<count($a);$i++) {
$b[] = array_sum(array_splice($a,0,$i));
}
I think, you want something like this:
for($i = 0; $i < count($a); $i++)
for($j = 0; $j < i + 1; $j++)
$b[i] += $a[j];
Related
So I have an array:
$array = array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
Obviously they're indexed 0-6.
I want to feed in a specific key index, and then reorder the array, beginning with that key, then going through the rest in the same order, like so:
print_r(somefunction(3, $array));
which would print this:
array
(
'0'=>'Wed',
'1'=>'Thu',
'2'=>'Fri',
'3'=>'Sat',
'4'=>'Sun',
'5'=>'Mon',
'6'=>'Tue'
)
Is there a core function that would do this, or does anyone have a quick solution?
UPDATE
Here's my final function, slightly bigger in scope than my question above, which utilizes AbraCadaver's answer:
public static function ordered_weekdays($format = 'abr')
{
$array = $format == 'full' ? array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday') : array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
return array_merge(array_splice($array, get_option('start_of_week'), count($array)-1), $array);
}
Because it's a nice one-liner, I didn't need to make it a separate function.
I've done this before and thought it was simpler than this, but here is what my brain says at the moment:
$index = 3;
$array = array_merge(array_splice($array, $index, count($array)-1), $array);
Try something along these lines...
function reorder($x,$y)
{
$c = count($y);
for ($i=0; $i<$c; $i++)
{
$newArray[$i] = $y[$x];
$x++;
if ($x > $c) $x = 0;
}
return($newArray);
}
function somefunction($n, array $a) {
$x = array_slice($a, 0, $n);
$y = array_slice($a, $n);
return array_merge($y, $x);
}
// forget this: uneccessary looping...
function somefunction($n, array $a) {
for($i = 0; $i < $n; $i++) {
array_push($a, array_shift($a));
}
return $a;
}
I want to tell my array to start from key position 2 and then loop through the entire array, including the values before key position 2. I just want to use one array and specify the key position I start looping from. For example, here I am using array_splice, but it does not do what I want it to, could you help me please?
$names = array('Bill', 'Ben', 'Bert', 'Ernie');
foreach(array_slice($names, 2) as $name){
echo $name;
}
foreach(array_slice($names, 3) as $name){
echo $name;
}
If the keys are irrelevant, you can splice the array twice, and merge the resulting arrays, like this:
$names = array('Bill', 'Ben', 'Bert', 'Ernie');
$start = 2;
foreach( array_merge( array_slice($names, $start), array_slice( $names, 0, $start)) as $name){
echo $name;
}
You can see from the demo that this prints:
BertErnieBillBen
Alternatively, for efficiency, you can use two loops that are aware of wrapping around to the beginning, which will be more efficient since you are operating on the original array and not creating copies of it.
$start = 2;
for( $i = $start, $count = count( $names); $i < $count; $i++) {
echo $names[$i];
}
$i = 0;
while( $i < $start) {
echo $names[$i++];
}
You could also turn this into one single loop, and just encapsulate the logic for wrapping around inside the for.
$limit = 2; //so you can set your start index to an arbitrary number
$fn= function($a,$b) use ($limit){
if(($a < $limit && $b < $limit)
|| ($a >= $limit && $b >=$limit)) //$a and $b on the same side of $limit
return $a < $b ? -1 : ($a==$b ? 0 : 1);
if($a < $limit && $b > $limit) return 1; //because $a will always be considered greater
if($a >= $limit && $b < $limit) return -1; //because $b will always be considered greater
};
uksort($arr, $fn);
foreach($arr as $v) echo $v;
I have an array of strings of random letters, and I need to know which letters are consistent between the array members. The count of the letters are important.
My method right now is loop through the array, doing a split, then looping through the spitted string to count the occurrences of each letter, then update the array with letter => count
Then do an array_reduce that creates a new array of members who only occur in all arrays. But, it's not working.
<?
$a[] = "emaijuqqrauw";
$a[] = "aaeggimqruuz";
$a[] = "aabimqrtuuzw";
$a[] = "aacikmqruuxz";
$a[] = "aacikmqruuxz";
$a[] = "aaciimqruuxy";
foreach($a as $b){
$n = str_split($b, 1);
foreach($n as $z){
$arr[$z] = substr_count($b, $z);
}
ksort($arr);
$array[] = $arr;
unset($arr);
}
$n = array_reduce($array, function($result, $item){
if($result === null){
return $item;
}else{
foreach($item as $key => $val){
if(isset($result[$key])){
$new[$key] = $val;
}
}
return $new;
}
});
foreach($n as $key => $val){
echo str_repeat($key, $val);
}
This returns aaiimqruu - which is kinda right, but there's only 2 i's in the last element of the array. There's only one i in the rest. I'm not sure how to break that down farther and get it to return aaimqruu- which I'll then pop into a SQL query to find a matching word, aquarium
There's array_intersect(), which is most likely what you'd want. Given your $a array, you'd do something like:
$a = array(.... your array...);
$cnt = count($a);
for($i = 0; $i < $cnt; $i++) {
$a[$i] = explode('', $a[$i]); // split each string into array of letters
}
$common = $a[0]; // save the first element
for($i = 1; $i < $cnt; $i++) {
$common = array_intersect($common, $a[$i]);
}
var_dump($common);
How about you do it this way? Finds out the occurrence of an item throughout the array.
function findDuplicate($string, $array) {
$count = 0;
foreach($array as $item) {
$pieces = str_split($item);
$pcount= array_count_values($pieces);
if(isset($pcount[$string])) {
$count += $pcount[$string];
}
}
return $count;
}
echo findDuplicate("a",$a);
Tested :)
Gives 12, using your array, which is correct.
Update
My solution above already had your answer
$pieces = str_split($item);
$pcount= array_count_values($pieces);
//$pcount contains, every count like [a] => 2
Seems like array_reduce is the best function for what this purpose, however I just didn't think of adding a conditional to give me the desired effect.
$new[$key] = ($result[$key] > $val) ? $val : $result[$key];
to replace
$new[$key] = $val;
did the trick.
This question already has answers here:
How to filter an associative array comparing keys with values in an indexed array?
(12 answers)
Closed last year.
I have an associative arrays and an array of keys.
$A = array('a'=>'book', 'b'=>'pencil', 'c'=>'pen');
$B = array('a', 'b');
How I build an associative array from all element of $A where the key is in $B?
For the example above, the answer should be
$C = array('a'=>'book', 'b'=>'pencil');
$keys = array_flip($B);
$C = array_intersect_key($A,$keys);
array_intersect_key($A,array_combine($B,$B))
or better: array_intersect_key($my_array, array_flip($allowed))
from the question: PHP: How to use array_filter() to filter array keys?
Here's a simple solution which checks that the key exists in $A before appending it to $C
$A = array('a'=>'book', 'b'=>'pencil', 'c'=>'pen');
$B = array('a', 'b');
$C = array();
foreach ($B as $bval) {
// If the $B key exists in $A, add it to $C
if (isset($A[$bval])) $C[$bval] = $A[$bval];
}
var_dump($C);
// Prints:
array(2) {
["a"]=>
string(4) "book"
["b"]=>
string(6) "pencil"
}
$keys = array_keys($B);
$C = array();
foreach ($A as $key => $value)
{
if (in_array($key, $keys))
{
$C[$key] = $value;
}
}
To my immense surprise, the foreach loop method is faster.
The following quick benchmark script gives me results:
array_intersect_key: 0.76424908638
foreach loop: 0.6393928527832
$A = array('a'=>'book', 'b'=>'pencil', 'c'=>'pen');
$B = array('a', 'b');
$start = microtime(true);
for ($i = 0 ; $i < 1000000; $i++) {
$c = array_intersect_key($A,array_flip($B));
}
$t1 = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
$C = array();
foreach ($B as $bval) {
// If the $B key exists in $A, add it to $C
if (isset($A[$bval])) $C[$bval] = $A[$bval];
}
}
$t2 = microtime(true);
echo "array_intersect_key: " . ($t1 - $start), "\n";
echo "foreach loop: " . ($t2 - $t1), "\n";
Say I have this array:
$array[] = 'foo';
$array[] = 'apple';
$array[] = '1234567890;
I want to get the length of the longest string in this array. In this case the longest string is 1234567890 and its length is 10.
Is this possible without looping through the array and checking each element?
try
$maxlen = max(array_map('strlen', $ary));
Sure:
function getmax($array, $cur, $curmax) {
return $cur >= count($array) ? $curmax :
getmax($array, $cur + 1, strlen($array[$cur]) > strlen($array[$curmax])
? $cur : $curmax);
}
$index_of_longest = getmax($my_array, 0, 0);
No loop there. ;-)
A small addition to the ticket. I came here with a similar problem: Often you have to output just the longest string in an array.
For this, you can also use the top solution and extend it a little:
$lengths = array_map('strlen', $ary);
$longestString = $ary[array_search(max($lengths), $lengths)];
Loop through the arrays and use strlen to verify if the current length is longer than the previous.. and save the index of the longest string in a variable and use it later where you need that index.
Something like this..
$longest = 0;
for($i = 0; $i < count($array); $i++)
{
if($i > 0)
{
if(strlen($array[$i]) > strlen($array[$longest]))
{
$longest = $i;
}
}
}
This way you can find the shortest (or longest) element, but not its index.
$shortest = array_reduce($array, function ($a, $b) {
if ($a === null) {
return $b;
}
return strlen($a) < strlen($b) ? $a : $b;
});