Merge arrays with strings and delete repetitive values in PHP - php

From WP_Query I am dumping strings stored into separate arrays:
array(1) {
[0]=>
string(8) "Portugal"
}
array(1) {
[0]=>
string(5) "Spain"
}
array(1) {
[0]=>
string(5) "Italy"
}
array(1) {
[0]=>
string(6) "Monaco"
}
array(1) {
[0]=>
string(5) "Spain"
}
array(1) {
[0]=>
string(9) "Lithuania"
}
I am trying to merge those arrays into one array, delete repetitive strings like "Spain" and get the number of unique values.
I was trying to use array_merge():
$tester = array();
foreach($array_string as $value) {
array_merge($tester, $value);
}
$result = array_unique($tester);
print_r($result);
But without any decent results, error telling that <b>Warning</b>: array_merge(): Argument #2 is not an array Could someone tell where I am missing the point? Many thanks for all possible help, will be looking forward.

The code posted in the question is almost good. The intention is correct but you missed out a simple thing: you initialize $tester with an empty array and then never add something to it. In the end, it is still empty and array_unique() has nothing to do but return an empty array too.
The error is in the line:
array_merge($tester, $value);
array_merge() does not change the arrays passed to it as argument. It returns a new array that your code ignores (instead of saving it into $tester).
This is how your code should look like:
$tester = array();
foreach($array_string as $value) {
$tester = array_merge($tester, $value);
}
$result = array_unique($tester);
print_r($result);
Solution #2
You can use call_user_func_array() to invoke array_merge() and pass the values of $array_string as arguments. The returned array contains duplicates; passing it to array_unique() removes them:
$result = array_unique(call_user_func_array('array_merge', $array_string));
Solution #3
A simpler (and possibly faster) way to accomplish the same thing is to use array_column() to get the values into an array and then pass it to array_unique(), of course:
$result = array_unique(array_column($array_string, 0));
This solution works only with PHP 5.5 or newer (the array_column() function doesn't exist in older versions.)

To get the number of unique strings in the merged array you will have to set empty array before WP_Query
$tester = array();
Than inside while loop of WP_Query every string is put into separate array and pushed to $tester
foreach((array)$array_string as $key=>$value[0]) {
array_push($tester,$value);
}
Unique values in array $tester is found using array_unique() functions that should be placed after WP_Query while loop.
$unique_array_string = array_unique($tester, SORT_REGULAR);
$unique_string_number = sizeof($unique_array_string);

You will create an array and will take key of the array for cities names like spain..etc And it will give different cities name always...
$data= array();
$data1 = array("Portugal");
$data2 = array("Spain");
$data3 = array("Italy");
$data4 = array("Monaco");
$data5 = array("Spain");
$data6 = array("Lithuania");
$merge = array_merge($data1, $data2,$data3,$data4,$data5,$data6);
$data = array();
foreach($merge as $value) {
$data[$value] = $value;
}
echo '<pre>',print_r($data),'</pre>';

Related

Is it possible for an array to know its parent?

Consider this array:
$super = [
"first" => ["first1","first2"],
"second" => ["second1","second2"]
];
Now let's grab a reference to the subarray:
$sub = $super["second"];
How can I reference the super array from the sub array?
I'm looking for a way to do something like this:
var_dump($sub[../"first"]);
array (size=2)
0 => string 'first1' (length=6)
1 => string 'first2' (length=6)
NO, PHP Arrays are implemented as ordered hashmaps. Which means that every key in the array gets hashed and maps directly to a value. That value could be another array, sure, but the map does not go in reverse. So a value cannot map back to a key in PHP or in the implementation of any typical hashmap. The hash only goes one way.
So in $arr = ["foo" => ["bar"]] the key "foo" in the array $arr will map to the value ["bar"], which happens to be another array. But there is no way to go in reverse order (i.e. map the value ["bar"] back to the key "foo" in $arr).
If you want this kind of co-recursive relationship, like a tree or graph, it's actually easier to accomplish with objects, because objects don't have the same by copy-by-value semantics that arrays do.
$obj = new stdClass;
$obj->first = new stdClass;
$obj->second = new stdClass;
$obj->first->parent = $obj;
$obj->second->parent = $obj;
$obj->first->value = ["first1", "first2"];
$obj->second->value= ["second1","second2"];
$first = $obj->first; // now I can ask it for its parent
$second = $first->parent->second->value;
var_dump($second);
You get
array(2) {
[0]=>
string(7) "second1"
[1]=>
string(7) "second2"
}
Now it doesn't actually matter if you change the value from $first or $obj. The object remains intact, because PHP objects aren't stored directly in the variable. They are stored in a container that's abstracted away from userland and the variable merely holds a reference to this container. So $first and $obj still both point to the same object.
So continuing from the example above, if we tried something like this ...
$second = $first->parent->second;
$first->parent->second->value = ["I changed you!", "I changed you too!"];
// This magically gets the right value
var_dump($second->value, $obj->second->value);
array(2) {
[0]=>
string(14) "I changed you!"
[1]=>
string(18) "I changed you too!"
}
array(2) {
[0]=>
string(14) "I changed you!"
[1]=>
string(18) "I changed you too!"
}
You can only know what's the parent index of an index by creating custom function like this :
function get_parent($key, $arr){
$index = 0;
foreach($arr as $keyCur => $val){
if($keyCur === $key){
$ret = [];
$ret['indexOfKey'] = $index;
$ret['valueOfKey'] = $val;
return $ret;
}
$index++;
}
return false;
}

Iterating through a $_session array

I have created a session array as follows
$_SESSION['memberInfo']['memberFirstName'] = ($first_name);
$_SESSION['memberInfo']['memberLastName'] = ($surname);
$_SESSION['memberInfo']['hash'] = ($hash);
$_SESSION['memberInfo']['templateSrc'] = ($newTemplateSrc);
in other pages where I'm trying to get the values from the array I have tried foreach and while loops without success, I can see the array in a var_dump
var_dump($_SESSION['memberInfo']);
which shows in console as
array(4) {
["memberFirstName"]=>
string(8) "Geoffrey"
["memberLastName"]=>
string(6) "Turner"
["hash"]=>
string(60) "$2y$10$YBE1tc.BK7yq6bBr/JAlWuN0H8xGdoNSAWzU4/zfd1r3v7jprNBD2"
["templateSrc"]=>
string(61) "../userDirectory/558386500/html/Geoffrey_Turner_558386500.php"
}
in the pages where im trying to itterate the array I have tried using
foreach ($_SESSION['memberInfo'] as $name)
{
$first_name = $name['memberFirstName'];
}
the responce I get shows as
Warning: Illegal string offset 'memberFirstName'
which I believe suggests the itteration is reading an empty array
I can echo out the array using
foreach ($_SESSION['memberInfo'] as $key => $val) {
echo "$key = $val\n";
}
which results in
memberFirstName = Geoffrey
memberLastName = Turner
hash = $2y$10$YBE1tc.BK7yq6bBr/JAlWuN0H8xGdoNSAWzU4/zfd1r3v7jprNBD2
templateSrc = ../userDirectory/558386500/html/Geoffrey_Turner_558386500.php
but for the life of me I cannot seem to figure out how to get each of the array values individually and assign them to a variable
Your foreach makes no sense as you looping an trying to assing single variable too many times for no benefits. So this to be removed:
foreach ($_SESSION['memberInfo'] as $name =) {
$first_name = $name['memberFirstName'];
}
as all you need is:
$first_name = $_SESSION['memberInfo']['memberFirstName'];
how to get each of the array values individually and assign them to a variable
You can use extract which extracts each value and assigns it to a variable.
extract($_SESSION['memberInfo']) this should create the following variables
$memberFirstName, $memberLastName, $hash, $templateSrc
Here is a demo http://ideone.com/XYpC7n

php - push array into an array -(pushing both key and the array)

I am trying to add an array to an existing array. I am able to add the array using the array_push . The only problem is that when trying to add array that contains an array keys, it adds an extra array within the existing array.
It might be best if I show to you
foreach ($fields as $f)
{
if ($f == 'Thumbnail')
{
$thumnail = array('Thumbnail' => Assets::getProductThumbnail($row['id'] );
array_push($newrow, $thumnail);
}
else
{
$newrow[$f] = $row[$f];
}
}
The fields array above is part of an array that has been dynamically fed from an SQl query it is then fed into a new array called $newrow. However, to this $newrow array, I need to add the thumbnail array fields .
Below is the output ( using var_dump) from the above code. The only problem with the code is that I don't want to create a seperate array within the arrays. I just need it to be added to the array.
array(4) { ["Product ID"]=> string(7) "1007520"
["SKU"]=> string(5) "G1505"
["Name"]=> string(22) "150mm Oval Scale Ruler"
array(1) { ["Thumbnail"]=> string(77) "thumbnails/products/5036228.jpg" } }
I would really appreciate any advice.
All you really want is:
$newrow['Thumbnail'] = Assets::getProductThumbnail($row['id']);
You can use array_merge function
$newrow = array_merge($newrow, $thumnail);
Alternatively, you can also assign it directly to $newrow:
if ($f == 'Thumbnail')
$newrow[$f] = Assets::getProductThumbnail($row['id']);
else
...
Or if you want your code to be shorter:
foreach($fields as $f)
$newrow[$f] = ($f == 'Thumbnail')? Assets::getProductThumbnail($row['id']) : $row[$f];
But if you're getting paid by number of lines in your code, don't do this, stay on your code :) j/k

How to convert an array of arrays or objects to an associative array?

I'm used to perl's map() function where the callback can assign both the key and the value, thus creating an associative array where the input was a flat array. I'm aware of array_fill_keys() which can be useful if all you want to do is create a dictionary-style hash, but what if you don't necessarily want all values to be the same? Obviously all things can be done with foreach iteration, but what other (possibly more elegant) methods exist?
Edit: adding an example to clarify the transformation. Please don't get hung up on the transformation, the question is about transforming a flat list to a hash where we can't assume that all the values will be the same.
$original_array: ('a', 'b', 'c', 'd')
$new_hash: ('a'=>'yes', 'b'=>'no', 'c'=>'yes', 'd'=>'no')
*note: the values in this example are arbitrary, governed by some business logic that is not really relevant to this question. For example, perhaps it's based on the even-oddness of the ordinal value of the key
Real-world Example
So, using an answer that was provided here, here is how you could parse through the $_POST to get a list of only those input fields that match a given criteria. This could be useful, for example, if you have a lot of input fields in your form, but a certain group of them must be processed together.
In this case I have a number of input fields that represent mappings to a database. Each of the input fields looks like this:
<input name="field-user_email" value="2" /> where each of this type of field is prefixed with "field-".
what we want to do is, first, get a list of only those input fields who actually start with "field-", then we want to create an associative array called $mapped_fields that has the extracted field name as the key and the actual input field's value as the value.
$mapped_fields = array_reduce( preg_grep( '/field-.+/', array_keys( $_POST ) ), function( $hash, $field ){ $hash[substr( $field, 6 )] = $_POST[$field]; return $hash; } );
Which outputs:
Array ( [date_of_birth] => 1 [user_email] => 2 [last_name] => 3 [first_name] => 4 [current_position] => 6 )
(So, just to forestall the naysayers, let me agree that this bit of compact code is arguably a lot less readable that a simple loop that iterates through $_POST and, for each key, checks to see if it has the prefix, and if so, pops it and its value onto an array)
I had the exact same problem some days ago. It is not possible using array_map, but array_reduce does the trick.
$arr = array('a','b','c','d');
$assoc_arr = array_reduce($arr, function ($result, $item) {
$result[$item] = (($item == 'a') || ($item == 'c')) ? 'yes' : 'no';
return $result;
}, array());
var_dump($assoc_arr);
result:
array(4) { ["a"]=> string(3) "yes" ["b"]=> string(2) "no" ["c"]=> string(3) "yes" ["d"]=> string(2) "no" }
As far as I know, it is completely impossible in one expression, so you may as well use a foreach loop, à la
$new_hash = array();
foreach($original_array as $item) {
$new_hash[$item] = 'something';
}
If you need it in one expression, go ahead and make a function:
function array_map_keys($callback, $array) {
$result = array();
foreach($array as $item) {
$r = $callback($item);
$result[$r[0]] = $r[1];
}
return $result;
}
This is a clarification on my comment in the accepted method. Hopefully easier to read. This is from a WordPress class, thus the $wpdb reference to write data:
class SLPlus_Locations {
private $dbFields = array('name','address','city');
public function MakePersistent() {
global $wpdb;
$dataArray = array_reduce($this->dbFields,array($this,'mapPropertyToField'));
$wpdb->insert('wp_store_locator',$dataArray);
}
private function mapPropertyToField($result,$property) {
$result[$property] = $this->$property;
return $result;
}
}
Obviously there is a bit more to the complete solution, but the parts relevant to array_reduce() are present. Easier to read and more elegant than a foreach or forcing the issue through array_map() plus a custom insert statement.
Nice!
A good use case of yield operator!
$arr = array('a','b','c','d');
$fct = function(array $items) {
foreach($items as $letter)
{
yield sprintf("key-%s",
$letter
) => "yes";
}
};
$newArr = iterator_to_array($fct($arr));
which gives:
array(4) {
'key-a' =>
string(3) "yes"
'key-b' =>
string(3) "yes"
'key-c' =>
string(3) "yes"
'key-d' =>
string(3) "yes"
}

Problem with a while loop

My query does no return anything for my second index. It always sends me a message Notice: Undefined offset: 1. I tried doing with a for it is the same result, so I have read that my problem it is in the query, somebody told me let $stmt be null for freeing resources of my statement. I dont know what is wrong.
These are my methods. I dont know what to someone say use $database->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,true);
Example: $arrayDirectory[] = {'user1', 'user2'};
It must echo 1 2 but just prints me 1
for($i=0;$i<sizeof($arrayDirectory;$i++){
$res[$i] = $obj->obtainID($arrayDirectory[$i]);
echo $res[$i];
}
This is my obtainID method:
public function obtainID($user){
$conexion = $this->objConexion->configuracion();
$query = "CALL sp_xxx('$user')";
$stmt = $conexion->prepare($query);
$stmt->execute();
$resultado = $stmt->fetchColumn();
return $resultado;
}
$stmi = null where?
For one,
$arrayDirectory[] = {'user1', 'user2'};
is a syntax error. { ... } does not work for arrays in PHP. Maybe it's just a typo and you're getting PHP confused with javascsript.
But the bigger issue is the []. That tells PHP to treat $arrayDirectory as an array (fine), but PUSH as a single value whatever you're assigning.
If your code was really:
$arrayDirectory[] = array('user1', 'user2');
This would create the following structure:
array(1) {
[0]=>
array(2) {
[0]=>
string(5) "user1"
[1]=>
string(5) "user2"
}
}
Note that it's a 2-level array. A top level single-element array at index [0]. That element at 0 contains ANOTHER array, which contains your two usernames.
You should have this instead:
$arrayDirectory = array('user1', 'user2');
$res = array();
foreach($arrayDirectory as $user) {
$res[] = $obj->obtainID($user);
}
first of all you are wrong with your function, you forgot to add the ending ')' for sizeof function,also arrays aren't defined with { } you should use array( ) instead.
and finally you are doing a bad practice over there;
you should not call a function in a loop (sizeof()), like this every time the loop goes through it will initiate sizeof() function and it will take some resource, since sizeof($object) won't change while using the loop, you should save it in a variable
$sizeofobject = sizeof($object);
and use that variable in your loop instead

Categories