Array Reverse and sorting is possible? - php

I'm trying to sort names in alphabetical order after a reverse array.
It's a code done for ordering last name/first name in right order.
A few bugs, (like with names with middle names) but it works except the sorting.
Here is the code:
<?php
$terms = get_terms( 'pa_artist' );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
echo '<ul class="artists">';
foreach ( $terms as $term ) {
$array = explode(" ", $term->name);
if ($array[3]) {
$array[3] = strtoupper($array[3]);
$array[3] = "<strong>".$array[3]."</strong>";
}
elseif ($array[2]) {
$array[2] = strtoupper($array[2]);
$array[2] = "<strong>".$array[2]."</strong>";
} elseif ($array[1]) {
$array[1] = strtoupper($array[1]);
$array[1] = "<strong>".$array[1]."</strong>";
} else {
$array[0] = strtoupper($array[0]);
$array[0] = "<strong>".$array[0]."</strong>";
}
$rarray = array_reverse($array);
sort($rarray);
echo '<li>' . implode(" ", $rarray) . '</li>';
}
echo '</ul>';
}
For now the names are ordered as if the reverse was never done.
Some examples, at first it showed like this:
Auguste Renoir
Pablo Picasso
Paul Gauguin
After the reverse and If strings, it's like this:
RENOIR Auguste
PICASSO Pablo
GAUGUIN Paul
When i need it:
GAUGUIN Paul
PICASSO Pablo
RENOIR Auguste
I tried every sort fonction, can't make it work… I can't find a way to sort after a reverse array, is it even possible?
It's for a list of names builded with attributes on wordpress/woocommerce.

If I right understand -- it can be done simple like this:
$artists = array(
array('Auguste', '', 'Renoir'),
array('Pablo', '', 'Picasso'),
array('Paul', '', 'Gauguin'),
);
usort($artists, function($a, $b) {
return strcasecmp($a[2], $b[2]);
});
// print_r($artists);

You need to put each individual artist array into a bigger array, and then sort that:
<?php
$terms = get_terms( 'pa_artist' );
$artists = array();
foreach ( $terms as $term ) {
$array = explode(" ", $term->name);
if ($array[3]) {
$array[3] = strtoupper($array[3]);
$array[3] = "<strong>".$array[3]."</strong>";
}
elseif ($array[2]) {
$array[2] = strtoupper($array[2]);
$array[2] = "<strong>".$array[2]."</strong>";
} elseif ($array[1]) {
$array[1] = strtoupper($array[1]);
$array[1] = "<strong>".$array[1]."</strong>";
} else {
$array[0] = strtoupper($array[0]);
$array[0] = "<strong>".$array[0]."</strong>";
}
$rarray = array_reverse($array);
$artists[] = $rarray;
}
usort($artists, function($a, $b) {
return strcasecmp($a[2], $b[2]);
});
// now run your foreach loop again to output the markup you want...

Related

PHP make a multidimensional associative array from key names in a string separated by brackets

I have a string with a variable number of key names in brackets, example:
$str = '[key][subkey][otherkey]';
I need to make a multidimensional array that has the same keys represented in the string ($value is just a string value of no importance here):
$arr = [ 'key' => [ 'subkey' => [ 'otherkey' => $value ] ] ];
Or if you prefer this other notation:
$arr['key']['subkey']['otherkey'] = $value;
So ideally I would like to append array keys as I would do with strings, but that is not possible as far as I know. I don't think array_push() can help here. At first I thought I could use a regex to grab the values in square brackets from my string:
preg_match_all( '/\[([^\]]*)\]/', $str, $has_keys, PREG_PATTERN_ORDER );
But I would just have a non associative array without any hierarchy, that is no use to me.
So I came up with something along these lines:
$str = '[key][subkey][otherkey]';
$value = 'my_value';
$arr = [];
preg_match_all( '/\[([^\]]*)\]/', $str, $has_keys, PREG_PATTERN_ORDER );
if ( isset( $has_keys[1] ) ) {
$keys = $has_keys[1];
$k = count( $keys );
if ( $k > 1 ) {
for ( $i=0; $i<$k-1; $i++ ) {
$arr[$keys[$i]] = walk_keys( $keys, $i+1, $value );
}
} else {
$arr[$keys[0]] = $value;
}
$arr = array_slice( $arr, 0, 1 );
}
var_dump($arr);
function walk_keys( $keys, $i, $value ) {
$a = '';
if ( isset( $keys[$i+1] ) ) {
$a[$keys[$i]] = walk_keys( $keys, $i+1, $value );
} else {
$a[$keys[$i]] = $value;
}
return $a;
}
Now, this "works" (also if the string has a different number of 'keys') but to me it looks ugly and overcomplicated. Is there a better way to do this?
I always worry when I see preg_* and such a simple pattern to work with. I would probably go with something like this if you're confident in the format of $str
<?php
// initialize variables
$str = '[key][subkey][otherkey]';
$val = 'my value';
$arr = [];
// Get the keys we want to assign
$keys = explode('][', trim($str, '[]'));
// Get a reference to where we start
$curr = &$arr;
// Loops over keys
foreach($keys as $key) {
// get the reference for this key
$curr = &$curr[$key];
}
// Assign the value to our last reference
$curr = $val;
// visualize the output, so we know its right
var_dump($arr);
I've come up with a simple loop using array_combine():
$in = '[key][subkey][otherkey][subotherkey][foo]';
$value = 'works';
$output = [];
if(preg_match_all('~\[(.*?)\]~s', $in, $m)) { // Check if we got a match
$n_matches = count($m[1]); // Count them
$tmp = $value;
for($i = $n_matches - 1; $i >= 0; $i--) { // Loop through them in reverse order
$tmp = array_combine([$m[1][$i]], [$tmp]); // put $m[1][$i] as key and $tmp as value
}
$output = $tmp;
} else {
echo 'no matches';
}
print_r($output);
The output:
Array
(
[key] => Array
(
[subkey] => Array
(
[otherkey] => Array
(
[subotherkey] => Array
(
[foo] => works
)
)
)
)
)
Online demo

Create multidimensional array from keys

Is there a way to create dynamicaly multidimensional array? I have stored in database "path" for each field=>value like that:
field_name : [slideshow][slide][0][title]
field_value : my title
field_name : [slideshow][slide][0][desc]
field_value : my desc
field_name : [slideshow][slide][1][title]
field value : my other title
field_name : [slideshow][slide][1][desc]
field value : my other desc
field_name : [slideshow][settings][duration]
field value : 300
and now I'm trying to figure out how to make it an array again. Obviously there can be lots of fields and complexity so I wanted to avoid some recursions if possible, cause I'm not sure how it will impact performance.
I was playing around with variable variables and trying something like:
$array_name = 'arr';
${$array_name}[slideshow][slide][1][title] = $field->field_value;
print_r($arr);
but this works only if its literally that, and nothing like this works:
${$array_name}.$field->field_name = $field->field_value;
I basically need to store every field as individual row (e.g. for searches in those fields), values can be diffrent types (even serialized arrays), and contain html.
Any advice appreciate.
The basic idea is to split up your field_name string and loop over the parts backward to build up the array. Some recursion is used to merge the arrays, though any performance impact should be negligible.
Example:
// Set up sample data.
$field = new stdClass();
$field->field_name = '[slideshow][slide][0][title]';
$field->field_value = 'my title';
$fields[] = $field;
$field = new stdClass();
$field->field_name = '[slideshow][slide][0][desc]';
$field->field_value = 'my desc';
$fields[] = $field;
$field = new stdClass();
$field->field_name = '[slideshow][slide][1][title]';
$field->field_value = 'my other title';
$fields[] = $field;
$field = new stdClass();
$field->field_name = '[slideshow][slide][1][desc]';
$field->field_value = 'my other desc';
$fields[] = $field;
$field = new stdClass();
$field->field_name = '[slideshow][settings][duration]';
$field->field_value = '300';
$fields[] = $field;
// End sample data.
// array_merge_recursive() doesn't do what we want with numeric keys, so use this
function merge($base, $array) {
foreach ($array as $key => $value) {
if (isset($base[$key]) && is_array($base[$key]) && is_array($value)) {
$base[$key] = merge($base[$key], $value);
} else {
$base[$key] = $value;
}
}
return $base;
}
$result = [];
foreach ($fields as $field) {
$parts = array_reverse(explode('][', trim($field->field_name, '[]')));
$value = $field->field_value;
foreach ($parts as $part) {
$value = [$part => $value];
}
$result = merge($result, $value);
}
print_r($result);
Output:
Array
(
[slideshow] => Array
(
[slide] => Array
(
[0] => Array
(
[title] => my title
[desc] => my desc
)
[1] => Array
(
[title] => my other title
[desc] => my other desc
)
)
[settings] => Array
(
[duration] => 300
)
)
)
You could try something like this.
$cars = array
(
array("Volvo",22,18),
array("BMW",15,13),
array("Saab",5,2),
array("Land Rover",17,15)
);
<?php
echo $cars[0][0].": In stock: ".$cars[0][1].", sold: ".$cars[0][2].".<br>";
echo $cars[1][0].": In stock: ".$cars[1][1].", sold: ".$cars[1][2].".<br>";
echo $cars[2][0].": In stock: ".$cars[2][1].", sold: ".$cars[2][2].".<br>";
echo $cars[3][0].": In stock: ".$cars[3][1].", sold: ".$cars[3][2].".<br>";
?>
<?php
for ($row = 0; $row < 4; $row++) {
echo "<p><b>Row number $row</b></p>";
echo "<ul>";
for ($col = 0; $col < 3; $col++) {
echo "<li>".$cars[$row][$col]."</li>";
}
echo "</ul>";
}
?>

using 2 loops in PHP foreach(...)

I have this PHP foreach loop:
foreach($emails_list as $email)
but i want to do something like
foreach($emails_list as $email and $forename_list as $forename)
my code above the foreach loop is:
$sql2="SELECT * from contacts where company_sequence = '".$customersequence."' and contactstatus = '' ";
$rs2=mysql_query($sql2,$conn) or die(mysql_error());
while($result2=mysql_fetch_array($rs2))
{
$emails_list[] = $result2["email"];
}
si i want to be able to include $result["forename"]; within the loop too
will the above work to make 2 loops?
Not sure if understand, but try use for instead:
$emails_list = array("01#gmail.com", "02#gmail.com", "03#gmail.com", "04#gmail.com");
$forename_list = ("01 something", "02 something", "03 something", "04 something");
if($emails_list == $forename_list){
$count = count($emails_list);
for($i=0;$i<$count;$i++){
echo 'Email: '.$emails_list[$i].', Name: '.$forename_list[$i];
}
} else { echo 'Troubles'; }
there is no way to do this in foreach in a one statment
for this use for loop like
for ($i=0;$i<=count($emails_list); $i++) {
echo $emails_list[$i];
echo $forename_list[$i];
}
All the examples listed with a basic for loop will work fine for numeric arrays, however what about associative arrays?
The best way to do this would be something like the following:
$arr_1 = array( 'foo'=>'bar', 'fizz'=>'bang' );
$arr_2 = array( 'hello'=>1, 2=>'world' );
$array_size = count( $arr_1 ); // NOTE: This assumes the arrays are of the same size.
// Reset the internal array pointers
reset( $arr_1 );
reset( $arr_2 );
for ($i = 0; $i < $array_size; $i++ ) {
$first_array_element = current( $arr_1 );
$second_array_element = current( $arr_2 );
// code here
next( $arr_1 );
next( $arr_2 );
}
This will handle both associative and numeric arrays.

How to sort results (by name) of an array?

I am using which code which returns taxonomies which match 2 values.
Everything works as it should, but I can't figure out how to order my results. Right now they are displayed in some set order, it might be date not sure. I am trying to get them to display alphabetically (by name)..
My Code from my php template is pasted here http://pastie.org/5083124
The array I am talking about is this
<?php
foreach ( $all_terms as $all_term) {
//print_r($all_terms);
$tax_test = get_option('woo_categories_panel_taxonomies_'.$all_term->taxonomy);
$post_images = array();
$posts_aray = array();
$parent_id = $all_term->term_taxonomy_id;
$term_name = $all_term->name;
$term_parent = $all_term->parent;
$term_slug = $all_term->slug;
$term_id = $all_term->term_id;
$term_link = get_term_link( $all_term, $all_term->taxonomy );
$counter_value = $all_term->count;
?>
<div class="childListings">
<div class="block">
<a href="<?php echo $term_link; ?>">
<?php
$block_counter++;
?>
</a>
<h2><?php echo $term_name ?> <br/><span>(<?php echo $counter_value; ?> Solicitors)</span></h2>
</div><!-- /.block -->
</div><!-- /.child Listings-->
<?php
if ( $block_counter % 6 == 0 ) {
?>
<div class="fix"></div>
<?php
} // End IF Statement
// End IF Statement
?>
<?php
} // End For Loop
?>
I have looked at a few different options with $args and ksort, but I get a bit lost and can't seem to get my results on the frontend of the site to be sorted alphabetically.
Can anyone identify in my code how I would be able to have my results have a sort order?
Thanks
You can avoid bothering to sort in the PHP by sorting slightly earlier, when you're querying the database. This should be faster.
Change:
$all_terms = $wpdb->get_results("SELECT * FROM ipt1y7_term_taxonomy,ipt1y7_terms WHERE ipt1y7_term_taxonomy.parent='{$ex[2]}' AND ipt1y7_term_taxonomy.term_id=ipt1y7_terms.term_id");
...to:
$all_terms = $wpdb->get_results("SELECT * FROM ipt1y7_term_taxonomy,ipt1y7_terms WHERE ipt1y7_term_taxonomy.parent='{$ex[2]}' AND ipt1y7_term_taxonomy.term_id=ipt1y7_terms.term_id ORDER BY ipt1y7_terms.name");
i.e. just add ORDER BY name to your original query. The results will be returned sorted by name with no need for you to do anything further in the PHP, and the sort will happen on the database server. The WordPress database table terms has an index on the name column, so this should be very fast; effectively the data is pre-sorted for you. (See the description of the terms table in the WP database schema.)
Have a look at the examples in http://php.net/manual/en/function.sort.php
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach ($fruits as $key => $val) {
echo "fruits[" . $key . "] = " . $val . "\n";
}
The above example will output:
fruits[0] = apple
fruits[1] = banana
fruits[2] = lemon
fruits[3] = orange
This is possible using usort and your own comparison function:
<?php
/**
* For a bit of testing.
*/
$all_terms = array( );
$names = array( 'foo', 'baz', 'bar', 'qux', 'aaa' );
foreach( $names as $name ) {
$tmp = new stdClass();
$tmp->name = $name;
$all_terms[] = $tmp;
}
/**
* Here, we do the sorting:
*/
usort( $all_terms, function( $a, $b ) {
if( $a->name === $b->name ) {
return 0;
}
return ( $a->name < $b->name ) ? -1 : 1;
});
/**
* And the results:
*/
var_dump( $all_terms );

php cutting multidimensional array

Anyone can help me with a function or point me into the direction on cutting a multidimensional array?
Here is what I need:
$array[x][y][b][q][o][p];
$array[b][c][f][q][l][v];
$newArray = cut_array_depth($array, 2);
// Would return a new array with a maximum dimension of 2 elements
// all others would be left out
$newArray[][];
Thanks,
You can write yourself the solution (even if I don't really understand the 'cutting' logic)
<?php
function cut_array_depth($array, $depth, $currDepth = 0){
if($currDepth > $dept){
return null;
}
$returnArray = array();
foreach( $array as $key => $value ){
if( is_array( $value ) ){
$returnArray[$key] = cut_array_depth($value, $depth , $currDepth +1);
} else {
$returnArray[$key] = $value;
}
return $returnArray;
}
?>

Categories