I'm running a foreach loop for the whole script that checks 9 things.
Let's say five of them have value "a" and four of them have value "b".
How do I write an IF condition (or something) that only returns "a" and "b" once?
Simple method (check last value)
Use a variable which stores the previous contents, and compare it with the current iteration (only works if the similar items are sequential)
$last_thing = NULL;
foreach ($things as $thing) {
// Only do it if the current thing is not the same as the last thing...
if ($thing != $last_thing) {
// do the thing
}
// Store the current thing for the next loop
$last_thing = $thing;
}
More robust method (store used values on an array)
Or, if you have complex objects, where you need to check an inner property and the like things are not sequential, store the ones used onto an array:
$used = array();
foreach ($things as $thing) {
// Check if it has already been used (exists in the $used array)
if (!in_array($thing, $used)) {
// do the thing
// and add it to the $used array
$used[] = $thing;
}
}
For example (1):
// Like objects are non-sequential
$things = array('a','a','a','b','b');
$last_thing = NULL;
foreach ($things as $thing) {
if ($thing != $last_thing) {
echo $thing . "\n";
}
$last_thing = $thing;
}
// Outputs
a
b
For example (2)
$things = array('a','b','b','b','a');
$used = array();
foreach ($things as $thing) {
if (!in_array($thing, $used)) {
echo $thing . "\n";
$used[] = $thing;
}
}
// Outputs
a
b
Could you be more concrete (it might be helpful to insert a code-snippet with your "content"-objects).
It sounds like, you are trying to get unique values of an array:
$values = array(1,2,2,2,2,4,6,8);
print_r(array_unique($values));
>> array(1,2,4,6,8)
Related
I have this code
$data['events'] = $this->calendar_model->get_events();
foreach ($data['events'] as $arr) {
settype($arr,"array");
$arr['something'] = false;
//print_r($arr);
}
echo json_encode($arr);
what I am trying to do is to add something => false to each record of the array
so lets say I got from the database
array of
title:"aaaaa",
start: "xxxx",
end: "cccc",
I want to add to each one something :false to become like
title:"aaaaa",
start: "xxxx",
end: "cccc",
something,false
for each record
but the problem is when I print using the print_r its fine, but the json_encode print only the last one.
Passing by value vs. by reference
You are passing your $arr by value in your foreach loop. Try to pass it by reference.
This is done by adding a & just before your $arr variable in your loop declaration:
foreach ($data['events'] as &$arr) {
settype($arr,"array");
$arr['something'] = false;
}
echo json_encode($data['events']);
How it works
Passing by value means that your foreach loop instanciates a local copy or your array. All modifications made inside the loop will affect only the local copy.
Passing by reference means that inside your loop, you are working directly on the original array. But be careful when doing that because it can be dangerous. For instance, I don't know what are the consequences of calling setType($arr,"array"); for the rest of your code.
You're not collecting $arr from each iteration of your loop into anything. It looks like you probably want to push $arr onto another array that stores everything, and then JSON encode that new array.
Try this:
$collection = array();
$data['events'] = $this->calendar_model->get_events();
foreach ($data['events'] as $arr) {
settype($arr,"array");
$arr['something'] = false;
array_push($collection, $arr);
}
echo json_encode($collection);
$data['events'] = $this->calendar_model->get_events();
foreach ($data['events'] as &$arr) {
settype($arr,"array");//This if there is not array
$arr['something'] = false;
}
echo json_encode($data['events']);
Try to make your own json like this
$strJson = '';
$data['events'] = $this->calendar_model->get_events();
foreach ($data['events'] as $arr) {
settype($arr,"array");
$arr['something'] = false;
//Assign value as yours in blow code
$strJson .= '{"title" : "'.$arr.'","start" : "'.$arr.'","end" : "'.$arr.'"},';
}
$strJson1=rtrim($strJson, ",");
$newStr = '['.$strJson1.']';
echo $newStr;
I have a database with some questions and I want every time the page is opened, not refreshed to show them in different order.
The shuffling, it's ok :
function shuffle_keys( &$array ) {
$keys = array_keys($array);
shuffle($keys);
foreach($keys as $key) {
$new[$key] = $array[$key];
}
$array = $new;
}
Shuffle the array with values from database and printing it:
shuffle_keys($array_questions);
foreach( $array_questions as $key => $val ) {
$key_value = ++$key;
echo "<a href = '?id=$val'>".$key_value."</a> ";
}
Just now, when I refresh every time the shuffling is different I want it this way only when I first open the page.
If you want to have the same shuffling for the same session, (that's what I understood)
You can use a $_SESSION variable to store your array.
session_start();
if (isset($_SESSION['array_questions']))
$array_questions=$_SESSION['array_questions'];
else
{
shuffle_keys($array_questions);
foreach( $array_questions as $key => $val ) {
$key_value = ++$key;
echo "<a href = '?id=$val'>".$key_value."</a> ";
}
$_SESSION['array_questions']=$array_questions;
}
You cannot detect a page refresh on its own. Perhaps consider setting a cookie and asserting whether it exists on page open?
You can use a static variable for the purpose. Just create a class as below:
class Base {
protected static $variable = 0;
}
class child extends Base {
function set() {
self::$variable = 1; // let say 1 = 'sorted'
}
function show() {
echo(self::$variable);
}
}
Now when you enter your site,
Create an object and set the variable, calling the method
$c1 = new Child();
if($c1->show() == 0)
{
// sort your array here and set the static flag to sorted(1)
$c1->set();
}
Hope this help...
1. PHP function.
I've created validating function, here it is in shorter version:
function my_function($input) {
$settings = my_source(); // function taht outputs a long array
foreach ($settings as $setting) {
$id = $setting['id'];
$foo = $setting['foo'];
$option = get_option('my_theme_settings');
if($foo == "bar") {
$valid_input[$id] = $input[$id];
}
}
return $valid_input;
};
Basically it takes $input and saves it as $valid_input. When it gets new $input it overwrites the old #valid_inpu and so on.
I want to create an additional $valid_input[$id] array that will not overwrite itself, but just push new elements inside.
2. Array_push() that doesn't work.
So the new updated code will look like that:
function my_function($input) {
$settings = my_source(); // function taht outputs a long array
foreach ($settings as $setting) {
$id = $setting['id'];
$foo = $setting['foo'];
$option = get_option('my_theme_settings');
if($foo == "bar") {
$valid_input[$id] = $input[$id];
}
else if($foo == "noupdate") { // it doesn't work
$valid_input[$id] = array();
array_push($valid_input[$id], $input[$id]);
}
}
return $valid_input;
};
As mentioned in comment above - this doesn't work, input always overwrites the option, it creates an array but it always contains only one element that is being erased with the new one (I guess array_push should prevent that behavior, right?).
3. The same happens with $array[] =
function my_function($input) {
$settings = my_source(); // function taht outputs a long array
foreach ($settings as $setting) {
$id = $setting['id'];
$foo = $setting['foo'];
$option = get_option('my_theme_settings');
if($foo == "bar") {
$valid_input[$id] = $input[$id];
}
else if($foo == "noupdate") { // it doesn't work
$valid_input[$id][] = $input[$id];
}
}
return $valid_input;
};
Still it overwrites the old value of $valid_input instead of pushing an element.
Any ideas? Maybe there's something wrong with the code? This whole function a Wordpress callback for function called register_setting(), but I guess it's mostly PHP related as folks on WPSE can't help me.
4. EDIT
This does exactly what I want, but why point 3. doesn't work then?
else if($foo == "noupdate") { // it doesn't work
$valid_input[$id][] = 'something';
$valid_input[$id][] = 'something_else';
$valid_input[$id][] = 'something_else2';
}
$valid_input[$id] needs to be set to array before you treat it as one.
$valid_input[$id] = array();
array_push( $valid_input[$id], "some stuff");
Same deal with [] notation
$valid_input[$id] = array();
$valid_input[$id][] = "some stuff";
To check if the array has been declared, so this:
if(!is_array($valid_input[$id]){
$valid_input[$id] = array();
}
The thing is that objects are passed as reference. you need to clone the objects before using the array_push function. here is a sample function that will clone an object:
function DeepCopy($ObjectToCopy) {
return unserialize(serialize($ObjectToCopy));
}
then you can use it this way
array_push($MyObjectsArray, DeepCopy($MyObject));
is it possible that you are trying to push a new value to the array with a key value that already exists? i would test for an existing key value in your array before trying to push a value/key pair to it. example:
if ( !isset( $arr[ $key ] ) ) {
$arr[ $key ] = $value;
} else {
echo " duplicate key value ";
}
Either array_push() or a variable used with the array append operator [] need to actually be an array or these won't work. Double check that whatever is in $valid_input[$id] is an array before doing array operations on the variable. Check by doing:
if (is_array($valid_input[$id])) {
// your code
}
Hi I have a PHP array with a variable number of keys (keys are 0,1,2,3,4.. etc)
I want to process the first value differently, and then the rest of the values the same.
What's the best way to do this?
$first = array_shift($array);
// do something with $first
foreach ($array as $key => $value) {
// do something with $key and $value
}
I would do this:
$firstDone = FALSE;
foreach ($array as $value) {
if (!$firstDone) {
// Process first value here
$firstDone = TRUE;
} else {
// Process other values here
}
}
...but whether that is the best way is debatable. I would use foreach over any other method, because then it does not matter what the keys are.
Here is one way:
$first = true;
foreach($array as $key => $value) {
if ($first) {
// something different
$first = false;
}
else {
// regular logic
}
}
$i = 0;
foreach($ur_array as $key => $val) {
if($i == 0) {
//first index
}
else {
//do something else
}
$i++;
}
I would do it like this if you're sure the array contains at least one entry:
processFirst($myArray[0]);
for ($i=1; $i<count($myArray); $1++)
{
processRest($myArray[$i]);
}
Otherwise you'll need to test this before processing the first element
I've made you a function!
function arrayCallback(&$array) {
$callbacks = func_get_args(); // get all arguments
array_shift($callbacks); // remove first element, we only want the callbacks
$callbackindex = 0;
foreach($array as $value) {
// call callback
$callbacks[$callbackindex]($value);
// make sure it keeps using last callback in case the array is bigger than the amount of callbacks
if(count($callbacks) > $callbackindex + 1) {
$callbackindex++;
}
}
}
If you call this function, it accepts an array and infinite callback arguments. When the array is bigger than the amount of supplied functions, it stays at the last function.
You can simply call it like this:
arrayCallback($array, function($value) {
print 'callback one: ' . $value;
}, function($value) {
print 'callback two: ' . $value;
});
EDIT
If you wish to avoid using a function like this, feel free to pick any of the other correct answers. It's just what you prefer really. If you're repeatedly are planning to loop through one or multiple arrays with different callbacks I suggest to use a function to re-use code. (I'm an optimisation freak)
In php I am converting posted data from a form to objects like this:
<?php
...some code...
$post = new stdClass;
foreach ($_POST as $key => $val)
$post->$key = trim(strip_tags($_POST[$key]));
?>
Then in my page I just echo posted data like this :
<?php echo $post->Name; ?>
<?php echo $post->Address; ?>
etc...
This works fine but I have multiple checkboxes that are part of a group and I echo the results of that, like this:
<?php
$colors = $_POST['color_type'];
if(empty($colors))
{
echo("No color Type Selected.");
}
else
{
$N = count($colors);
for($i=0; $i < $N; $i++)
{
echo($colors[$i] . ", ");
}
}
?>
That works when I am just using array, but how do I write this as object syntax?
using your code
function array_to_object($arr) {
$post = new stdClass;
foreach ($arr as $key => $val) {
if(is_array($val)) {
$post->$key = post_object($val);
}else{
$post->$key = trim(strip_tags($arr[$key]));
}
}
return $post;
}
$post = array_to_object($_POST);
or more complex solution
function arrayToObject($array) {
if(!is_array($array)) {
return $array;
}
$object = new stdClass();
if (is_array($array) && count($array) > 0) {
foreach ($array as $name=>$value) {
$name = strtolower(trim($name));
if (!empty($name)) {
$object->$name = arrayToObject($value);
}
}
return $object;
}
else {
return FALSE;
}
}
from http://www.richardcastera.com/blog/php-convert-array-to-object-with-stdclass
why would you want that? What's wrong with an array?
Use Object Oriented Programming, which might be what you are looking for. Treat it as an object, by making a class called Color and doing $colors[$i] = new Color();
This way you can do whatever you want with it, and add functions to it.
Pretty simple -- when you attach the color_type key to your object, it'll become an array that's a property of your object. This is most likely what you want: you probably won't want to turn that array into its own stdClass-based object, because then you won't be able to iterate through all the values (as easily). Here's a snippet:
<?php
// putting in both of these checks prevents you from throwing an E_WARNING
// for a non-existent property. E_WARNINGs aren't dangerous, but it makes
// your error messages cleaner when you don't have to wade through a bunch
// of E_WARNINGS.
if (!isset($post->color_type) || empty($post->color_type)) {
echo 'No colour type selected.'; // apologies for the Canadian spelling!
} else {
// this loop does exactly the same thing as your loop, but it makes it a
// bit more succinct -- you don't have to store the count of array values
// in $N. Bit of syntax that speeds things up!
foreach ($post->color_type as $thisColor) {
echo $thisColor;
}
}
?>
Hope this helps! Of course, in a real-life setting, you'll want to do all sorts of data validation and cleaning -- for instance, you'll want to check that the browser actually passed an array of values for $_POST['color_type'], and you'll want to clean the output in case someone is trying to inject an exploit into your page (by going echo htmlspecialchars($thisColor); -- this turns all characters like < and > into HTML entities so they can't insert JavaScript code).