I write a multilingual wordpress homepage. I need to load all languages into array, then detect the user language and then depending on user language remove the other languages from the array.
I want to do partial check on array to see if "Title" contains _DE or _ES and then depending on result remove one or the other from array.
So far I have
Data
array(2) {
[1]=> array(3) { ["order"]=> string(1) "1" ["title"]=> string(9) "Slider_ES" ["id"]=> string(3) "500" }
[2]=> array(3) { ["order"]=> string(1) "2" ["title"]=> string(11) "Slider_DE" ["id"]=> string(3) "493" }
}
Logic
$current_language = get_locale(); // Wordpress function which returns either es_ES or de_DE codes
if ($current_language == es-ES) {
foreach ($array as $key => $item) {
if ($item['title'] === '_DE') {
unset($array[$key]);
}
}
} else {
foreach ($array as $key => $item) {
if ($item['title'] === '_ES') {
unset($array[$key]);
}
}
}
What did I miss?
You can use the strpos function which is used to find the occurrence of one string inside other like this:
if (strpos($item['title'],'_DE') !== false) {
unset($array[$key]);
}
Related
I have tried all the solutions suggested in this post but have not been able to make them work in my case.
My array :
array(2) {
["number_s"]=>
array(14) {
[0]=>
string(2) "22"
[1]=>
string(2) "23"
[2]=>
string(0) ""
[3]=>
string(0) ""
[4]=>
string(0) ""
}
["player_name"]=>
array(14) {
[0]=>
string(9) "John Doe"
[1]=>
string(11) "Jack Sparrow"
[2]=>
string(0) ""
[3]=>
string(0) ""
[4]=>
string(0) ""
}
}
I would like to remove all the empty entries but how to do that ?
Thanks a lot for help
It seems like array_filter for each subarray will do what you want.
$array['number_s'] = array_filter($array['number_s']);
$array['player_name'] = array_filter($array['player_name']);
When called without callback function it just removes all empty entries. See docs for details.
But be aware that it will remove "0" and all values which considered empty.
Assuming there aren't arbitrary numbers of subarrays, you may transverse them (as references) and use unset to remove them from the array:
foreach ($array as &$subarray) {
foreach ($subarray as $key => $value) {
if (empty($value)) {
unset($subarray[$key]);
}
}
}
It's simpler with a functional approach:
$array = array_map(
fn($subarray) => array_filter($subarray),
$array
);
If the array may have arbitrary levels, you may implement a recursive function:
function remove_empty_recursive(array &$array)
{
foreach($array as $key => &$value) {
if (empty($value)) {
unset($array[$key]);
} elseif (is_array($value)) {
remove_empty_recursive($value);
}
}
}
Notice all those solutions assume you want to remove "0", 0 and false from the array. Otherwise, you need to specify another criteria, instead of using empty. For instance:
$array = array_map(
fn($subarray) => array_filter(
$subarray,
fn($value) => !empty($value) || is_numeric($value) || $value === false
),
$array
);
I return this array of objects from an API call like so. Note that $result is an array of arrays with $result[data] holding todo list objects and result[success] holding status of API call:
array(9) { [0]=> object(stdClass)#3 (5) { ["todo_id"]=> string(10) "1480430478" ["title"]=> string(13) "Check Printer" ["description"]=> string(8)
"Room 233" ["due_date"]=> string(10) "11/29/2016" ["is_done"]=> string(4) "true" } [1]=> object(stdClass)#4 (5) { ["todo_id"]=> string(10) "148043046" ["title"]=> string(18) "Doctor Appointment" ["description"]=> string(7)
"#4pm. " ["due_date"]=> string(10) "11/30/2016" ["is_done"]=> string(4) "true" }
etc..
I sort the array with usort fine and then I want to resort on the "is_done" field and put them at bottom of todo list in date order. The php to do this is :
//Sort by is_done
foreach($result[data] as $arrayElement ) {
foreach($arrayElement as $valueKey => $value) {
if(($valueKey == 'is_done') && ($value == 'true')){
$temp = $arrayElement;
//delete this particular object from the $array
unset($result[data][$arrayElement]);
array_push($result[data], $temp);
}
}
}
The problem I am having is my completed items are now at the end of the array but they are also still in their original position. The unset is not working. I have tried all variations on referencing the $result[data] item to no avail. This is probably something simple but I need some help if possible. Googling and checking this site shows no examples of unset in this type of situation. Thanks in advance.
Update:
after applying colburton's solution the API is now returning this data structure:
object(stdClass)#3 (6) { ["2"]=> object(stdClass)#4 (5) { ["todo_id"]=> int(1480698596) ["title"]=> string(7) "Test #4" ["description"]=> string(4) "test" ["due_date"]=> string(10) "12/02/2016" ["is_done"]=> string(5) "false" } ["3"]=> object(stdClass)#5 (5) { ["todo_id"]=> string(10) "1480617975" ["title"]=> string(13) "Check Printer" ["description"]=> string(4)
"Test" ["due_date"]=> string(10) "12/06/2016" ["is_done"]=> string(5) "false" } ["5"]=> object(stdClass)#6 (5) { ["todo_id"]=> int(1481136023) ["title"]=> string(9) "Todo item" ["description"]=> string(7) "test123" ["due_date"]=> string(10) "01/19/2017" ["is_done"]=> string(5) "false" } etc...
At the end of the call i do a
//json_decode the result
$result = #json_decode($result);
//check if we're able to json_decode the result correctly
if ($result == false || isset($result->success) == false) {
throw new Exception('Request was not correct');
}
//if there was an error in the request, throw an exception
if ($result->success == false) {
throw new Exception($result['errormsg']);
}
//if everything went great, return the data
return $result->data;
}
and then in main program I reference $result as
$result = $todo_items[0];
And that is where fatal error occurs now.
Update II:
Wanted to add that you then need to reindex the array
$result['data'] = array_values($result['data']);
I read here that this is a bug in json_decode. Thanks for the help....
Please use quotes around your array indices. This unsets what you want:
foreach ($result['data'] as $idx => $arrayElement) {
foreach ($arrayElement as $valueKey => $value) {
if (($valueKey == 'is_done') && ($value == 'true')) {
$temp = $arrayElement;
//delete this particular object from the $array
array_push($result['data'], $temp);
unset($result['data'][$idx]);
}
}
}
I have this array:
array(5) {
[0]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[1]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
[2]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "3"
["productTxtVal"]=>
string(5) "Text3"
}
[3]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[4]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
}
With the above input, I want the output array to look like this:
array(2) {
[0]=>
array(3) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTxtVal"]=>
string(17) "Text1 Text2 Text3"
}
[1]=>
array(3) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTxtVal"]=>
string(11) "Text1 Text2"
}
}
The resulting array does not need the productTextSeq key, just the combined values of productTextVal, when the productCode is the same. I've searched SO for examples of this but it seems every example I've found are based on multiple input arrays. I know I can brute force this with nested foreach functions but would love a more elegant solution.
I ended up just doing it the brute force method, here is my solution if anyone's interested:
$productData = array();
$sortedData = array();
$comments = '';
$saveKey = '';
$appendComment = false;
$idx = 0;
foreach ($data as $key=>$value) {
foreach ($value as $k=>$v) {
if ($k == 'productCode') {
if ($v == $saveKey) {
$appendComment = true;
} else {
$appendComment = false;
$saveKey = $v;
if ($idx !== 0) { // Don't write to array on first iteration!
$productData['productTxtVal'] = $comments;
$sortedData[] = $productData;
}
}
}
if ($k == 'productTxtVal') {
if ($appendComment == true) {
$comments .= ' ' . trim($v);
} else {
$comments = trim($v);
}
}
}
$productData = $value;
$idx++;
}
Not "elegant" but it works. I also have a check after this logic in case only one productCode is in the original array, as it won't be written to the $sortedData array since the key never changes.
The following code assumes you control the contents of the original data array (due to risk of injection using extract() function) and that no 2 items with the same productCode have the same productTextSeq.
$products = [];
foreach ($data as $item) {
// extract contents of item array into variables
extract($item);
if (!isset($products[$productCode])) {
// create product array with code, upc, text as array
$products[$productCode] = compact('productCode', 'productUPC') + ['productTxtVal' => []];
}
// add text value to array with sequence as index
$products[$productCode]['productTxtVal'][$productTextSeq] = $productTxtVal;
}
$products = array_values( // ignore array keys
array_map(function($product) {
ksort($product['productTxtVal']); // sort text as array by index/ sequence
$product['productTxtVal'] = implode(' ', $product['productTxtVal']); // implode into string
return $product;
}, $products)
);
You can run the code here: https://repl.it/BWQL
Absolutely doing my head in here over something that I'm sure is very simple...
I have 2 arrays.
$post_cats which are categories that any given post is in.
$ad_cats which is an array of categories in which ads are placed.
Basically, if a post has in its array of selected categories, a category that matches an item in the array of ad categories, then it must return the matching value/item.
$post_cats returns this
array(4) {
[0]=> array(1) { ["slug"]=> string(6) "energy" }
[1]=> array(1) { ["slug"]=> string(6) "global" }
[2]=> array(1) { ["slug"]=> string(8) "identify" }
[3]=> array(1) { ["slug"]=> string(5) "south" }
}
and $ad_cats returns this
array(6) {
[0]=> array(1) { ["slug"]=> string(5) "north" }
[1]=> array(1) { ["slug"]=> string(5) "south" }
[2]=> array(1) { ["slug"]=> string(4) "east" }
[3]=> array(1) { ["slug"]=> string(4) "west" }
[4]=> array(1) { ["slug"]=> string(6) "global" }
[5]=> array(1) { ["slug"]=> string(8) "fallback" }
}
The duplicated item there is "south", so in my mind the value of array_intersect($post_cats, $ad_cats); should be an array with a single item - "south", correct?
But its returning, what seems like, everything in either of the arrays... I can't for the life of me get it to work..
Using the above example, I need to return "south" to a variable.
So you are looking for items that are in both arrays? ...
What about something like this:
function find_duplicate($array1, $array2)
{
$list = array();
foreach($array1 as $value1)
{
foreach($array2 as $value2)
{
if($value1 == $value2) $list[] = $value1;
}
}
return $list;
}
The best way is to convert those arrays in arrays array_intersect can work with.
Considering:
$a; // first array
$b; // second array
then you would go with:
$a1 = array();
foreach ($a as $v) $a1[] = $v['slug'];
$b1 = array();
foreach ($b as $v) $b1[] = $v['slug'];
$c = array_intersect($a1, $b1);
PHP functions usually work with more powerful algorithms than what you may think; therefore it's a good choice to let PHP functions handle this kind of things.
This solution uses array_map to get at the values and takes the intersection of that
function mapper($a)
{
return $a['slug'];
}
$set1 = array_map('mapper', $post_cats);
$set2 = array_map('mapper', $ad_cats);
$result = array_intersect($set1, $set2);
PhpFiddle for testing.
array(2) {
["names"]=> array(4) {
[0]=> string(4) "Edit"
[1]=> string(6) "Delete"
[2]=> string(8) "Activate"
[3]=> string(10) "Deactivate"
}
["action"]=> array(4) {
[0]=> string(4) "ajax"
[1]=> string(4) "abc"
[2]=> string(4) "def"
[3]=> string(4) "xyz"
}
}
How do i loop through this in a single foreach loop?
Assuming both arrays are of the same size and have the same keys:
foreach($array['names'] as $k => $name) {
$action = $array['actions'][$k];
// do whatever you want to do with $name and $action
}
$newArr = array();
foreach($data['names'] as $i => $val) {
$newArr[$val] = $data['actions'][$i];
}
Or if you want a one liner at that
$newArr = array_combine($data['names'], $data['action']);
I guess the best way is a recursive function which can move through even three dimensions and more
function MoveThroughArray($arr)
{
foreach($arr as $value)
{
if(is_array($value))
MoveThroughArray($value);
else
// Do Something
}
}