0

I have this PHP array:

$this->user_list        = array( 0 => 'Not paid',1 => 'Not paid', 2 => 'Not paid', 7 => 'Waiting, 15 => 'Waiting', 10 => 'Cancelled' );

How can I simplify this array as the id numbers are different, but some of them have same status?

I tried it like this:

$this->user_list        = array( [0,1,2 => 'Not paid'],[7,15 => 'Waiting'],10 => 'Cancelled' );

but it doesn't work as expected.

Basically I want to achieve this:

echo $this->user_list[15] should give me Waiting, echo $this->user_list[10] should give me Cancelled, etc. So this is working in my first array very well, I am just thinking about grouping duplicate names there.

4
  • 2
    That's not a valid PHP structure. Perhaps you could use something like array('Not paid' => array(0, 1, 2), 'Waiting' => array(7, 15), 'Cancelled' => array(10)) Commented Aug 28, 2020 at 9:00
  • you are mixing single and two dimensional array. Commented Aug 28, 2020 at 9:00
  • Still I have empty results in your way. It works only with my first solution, which is not simplified Commented Aug 28, 2020 at 9:09
  • 1
    Based on your edit with desired results there is no better structure in php than the one you already have. Commented Aug 28, 2020 at 21:23

4 Answers 4

1

As mentioned by other contributors, there is no native support in the PHP grammar for your intended use case. As clearly stated in the PHP: Arrays documentation:

An array can be created using the array() language construct. It takes any number of comma-separated key => value pairs as arguments.

So basically each element in an array is a key => value pair, which means you cannot associate multiple keys to a single element.

This also explains why your first tentative didn't work:

$this->user_list = array( [0,1,2 => 'Not paid'],[7,15 => 'Waiting'],10 => 'Cancelled' );

If you don't specify a key for an element, PHP uses a progressive index (0, 1, ...). So basically in the example above, the first zero is not actually a key, but a value, and PHP binds it to the key = 0. Maybe it could be easier for you to understand how it works if you print a var_dump or print_r of $this->user_list. You would get something similar to the following structure (NOTE: I have simplified the structure to make it more clear):

[
  0 => [
      0 => 0
      1 => 1
      2 => "Not paid"
  ],
  1 => [
      0 => 7,
      15 => "Waiting"
  ],
  10 => "Cancelled"
]

So how do we resolve this problem? Well... actually there is no need to contort the structure by swapping keys with values as other contributors seem to suggest. Changing the structure might simplify your "data entry" work but might also create big issues in other parts of the program because who knows, maybe accessing the invoice data by "ID" is simply more efficient than by "status" ... or something.

Since PHP does not provide such a feature out of the box, I believe a better solution would be to develop our own function; a good starting point could be the one in the example below.

function explode_array($config, $sep = ',') {
    $res = [];
    foreach($config as $configKey => $value) {
        // split key values
        $keys = explode($sep, $configKey);
        foreach($keys as $key) {
            $res[$key] = $value;
        }
    }
    return $res;
}

$config = [
    '0,1,2' => 'Not paid',
    '7,15' => 'Waiting',
    '10' => 'Cancelled'
];
$myArr = explode_array($config);
print_r($myArr);

The idea is quite simple: since we cannot use an array as key we leverage the next best data type, that is a CSV string. Please note there is no error handling in the above code, so the first thing you may want to do is adding some validation code to the explode_array (or however you wish to name it) function.

Sign up to request clarification or add additional context in comments.

1 Comment

very well explained, thank you! With the explode_array it is working as expected.
1

you should use like this. if id number is invoice id or something else and other value is there status about it.

 $arr = array( 
   'Not paid' => [0,1,2] , 
   'Waiting' => [5,6],
   'Cancelled' =>[8]
);



foreach($arr as $key => $val){
 foreach($val as $keys => $vals){
 echo   "invoiceid ".$vals ." status ".$key;
 echo"<br>";
 }
}

// for only one status you can use like this

foreach($arr['Not paid'] as $key => $val){
 echo $val;
echo"<br>";
}

just try to run this and check output.

2 Comments

ok, this will work, but I want a result like this: $this->user_list[15] should give me Waiting. Then if I call $this->user_list[10] should give me Cancelled. This works in my first example. The only thing I want is to have the same array as in my question, just to group duplicite names to one, e.g. as in your $arr. I don't need cycle through array, I want just a result for any $this->user_list[ID]
Okay got it. Then you should use list this $user = array(); start foreach as mentioned above then inside foreach $user[$key] = $val; then print that array print_r($user); you will got value like this .
1

PHP has no built-in function or structure for handling cases like this. I'd use a simple array value-cloning function to map your duplicates. Simply have one instance of each status, then map the aliases, and then run a function that clones them in. As follows:

// Status list:
$ulist = [ 0 => 'Not paid', 7 => 'Waiting', 10 => 'Cancelled' ];

// Alternative IDs list, mapped to above source IDs:
$aliases = [ 0 => [1,2], 7 => [15] ];

// Function to clone array values:
function clone_values(array &$arr, array $aliases)
{
    foreach($aliases as $src => $tgts) {
        foreach($tgts as $tgt) {
            $arr[$tgt] = $arr[$src];
        }
    }
    ksort($arr); // If the order matters
}

// Let's clone:
clone_values($ulist, $aliases);

This results in the following array:

array(6) {
    [0] · string(8) "Not paid"
    [1] · string(8) "Not paid"
    [2] · string(8) "Not paid"
    [7] · string(7) "Waiting"
    [10] · string(9) "Cancelled"
    [15] · string(7) "Waiting"
}

....which can be accessed as you expect, here $ulist[2] => Not paid, etc. If the use case is as simple as illustrated in the OP, I'd personally just spell it out as is. There's no dramatic complexity to it. However, if you have dozens of aliases, mapping and cloning begins to make sense.

Comments

0

As said in the comments, you can't have multiple keys with one value. The best way is to use the keyword => [ number, number, number...] construction.

//set a result array
$result = [];

//loop the original array
foreach ( $this->user_list as $number => $keyword ){
  //if the keyword doesn't exist in the result, create one
  if(!isset ( $result [ $keyword ] ) ) $result[ $keyword ] = [];
  //add the number to the keyword-array 
  $result[ $keyword ] [] = $number;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.