Search code examples
phparraysexplodecountingdelimited

Split, group, count and display data from delimited strings


I have a list of teachers with properties like:

teacher 1 skills = English, Math
teacher 1 gender = Male

teacher 2 skills = Spanish, Math, Law
teacher 1 gender =  sex = Female

teacher 3 skills = English, Geography
teacher 3 gender = Male

First of all I want to tell how many English (and any other matter) teachers there are, since the skills can be various, what I do is to check for a duplicate in the array and count it:

     $stack = array();
     $blogusers = get_users( 'orderby=nicename&role=author' );
  foreach ( $blogusers as $user ) {
     $myUsers = $user->user_description (this is the skill list);
     $mystrings = strtolower($user->user_description);
     $descTokens = explode(',', $mystrings);
     $descTokens = array_map('trim',$descTokens);
     $stack = array_merge($stack, $descTokens);
  }
     $count_values = array();
     foreach ($stack as $a) {
       @$count_values[$a]++;
     }
     $total_duplicates = 0;
     foreach ($count_values as $a) {
       if($count_values[$a]<=1){
          unset($count_values[$a]);
       } else{
          $total_duplicates += $count_values[$a];
       }
      }

Then do this

    <ul class="margin-top-20">
      <?php
        foreach ($count_values as $key=>$count ) {
          echo '<li>'.$count.' di <strong>'.$key.'</li>';
        }
      ?>
    </ul>

That's correct, the output is right:

2 English teachers
2 Math teachers
1 Spanish
1 Law
1 Geography

But I also have the gender, so ideally I would like to have

2 English teachers, 1 male, 1 male
2 Math teachers, 1 male, 1 female
1 Spanish, 1 female
1 Law, 1 female
1 Geography, 1 male

I tried adding:

      $sex = array();
      $user_sex = get_user_meta( $the_user_id, $gender, $single ); 
      array_push($sex, $user_sex);
      foreach($descTokens as $lang){
        $userSex[$lang] += $user_sex;  
      }
      foreach ($count_values as $key=>$count ) {
        echo '<li>'.$count.' di <strong>'.$key.' gender '. $userSex[$key] .'</li>';
      }

But that's not right.

Fullcode I am trying:

  <?php
    $stack = array();
    $userID = array();
    $nPost = array();
    $listmaterie = array();
    $materie = array();
    $gender = 'sesso';
    $single = true;
    $sex = array();
    $blogusers = get_users( 'orderby=nicename&role=author' );
    $userSex = array();
    foreach ( $blogusers as $user ) {
        $myUsers = $user->user_description;
        $mystrings = strtolower($user->user_description);
        $descTokens = explode(',', $mystrings);
        $descTokens = array_map('trim',$descTokens);
        $stack = array_merge($stack, $descTokens);
        $the_user_id = $user->ID;
        $numPosts = count_user_posts( $the_user_id );
        array_push($userID, $the_user_id);
        array_push($nPost, $numPosts);
        $user_sex = get_user_meta( $the_user_id, $gender, $single ); 
        array_push($sex, $user_sex);
        foreach($descTokens as $lang){
          $userSex[$lang] += $user_sex;  
        }
     }
       // get the count for each language by counting the duplicate strings;
     $count_values = array();
     foreach ($stack as $a) {
       @$count_values[$a]++;
     }
     $total_duplicates = 0;
     foreach ($count_values as $a) {
       if($count_values[$a]<=1){
          unset($count_values[$a]);
       } else{
          $total_duplicates += $count_values[$a];
       }
      }
     $count_sex = array();
     foreach ($sex as $b) {
       @$count_sex[$b]++;
     }
     $total_duplicates_sex = 0;
     foreach ($count_sex as $b) {
       if($count_sex[$b]<=1){
          unset($count_sex[$b]);
       } else{
          $total_duplicates_sex += $count_sex[$b];
       }
      }
    ?>
    <h3 class="margin-top-40">Numero complessivo docenti su Jikū:</h3>
    <ul class="margin-top-20 margin-bottom-20">
    <?php
      $totalInsegnanti = count($userID);
      echo '<li>'. $totalInsegnanti .'</li>'; 
    ?>
    </ul>
    <h3>Totale insegnanti per materia su Jikū:</h3>
    <ul class="margin-top-20">
      <?php
        foreach ($count_values as $key=>$count ) {
          echo '<li>'.$count.' di <strong>'.$key.' gender '. $userSex[$key] .'</li>';
        }
      ?>
    </ul>
    <h3>Totale insegnanti sesso su Jikū:</h3>
    <ul class="margin-top-20">
      <?php 
        foreach ($count_sex as $key=>$count_sex) { 
            echo '<li>'.$count_sex.' <strong>'.$key.'</strong></li>'; 
        }
      ?>
    </ul>

Dumps I have 3 users

var_dump($stack);

array(11) { [0]=> string(8) "francese" [1]=> string(7) "chimica" [2]=> string(6) "fisica" [3]=> string(7) "scienze" [4]=> string(7) "inglese" [5]=> string(6) "fisica" [6]=> string(7) "chimica" [7]=> string(8) "spagnolo" [8]=> string(8) "francese" [9]=> string(6) "fisica" [10]=> string(8) "italiano" }

var_dump($sex);

array(3) { [0]=> string(7) "maschio" [1]=> string(7) "maschio" [2]=> string(7) "femmina" }


Solution

  • Code:

    foreach($blogusers as $user){
        foreach(explode(', ',$user->user_description) as $skill){  //"comma then space" delimited
            $result[$skill][]=get_user_meta($user->ID,'sesso','true');  // push user's gender into subject's array
        }
    }
    
    foreach($result as $subject=>$gender_array){
        echo "<div>",sizeof($gender_array)," $subject teachers";
        $count_genders=array_count_values($gender_array);  // avoids php NOTICE @ array_walk
        array_walk($count_genders,function($v,$k){echo ", $v $k",($v!=1?"s":"");});
        echo "</div>";
    }
    

    Considering your sample input data, my method will output this:

    2 English teachers, 2 Males
    2 Math teachers, 1 Male, 1 Female
    1 Spanish teachers, 1 Female
    1 Law teachers, 1 Female
    1 Geography teachers, 1 Male