Make the array have at least one element with each of a specific value

I am making a combined media feed class that receives Facebook and blogger posts and tweets from Twitter. Then it combines them into one list for display on the site. The problem is that you rarely see any of the message types, because twitter is much more active than the other two.

I managed to display at least one of each type, however, I did this by counting the number of each type in the final array and then splicing them to the end if there were none, and I wonder if there is a more elegant solution for this?

My array contains many arrays, each of which has a type value, this is what I need to check for / to have at least one of them.

before splicing:

Array ( [0] => Array ( [id] => 131403235838803968 [from] => foo [sent] => 1320163947 [type] => tweet [html] => bar ) [1] => Array ( [id] => 131403233250914304 [from] => foo [sent] => 1320163946 [type] => tweet [html] => bar ) [2] => Array ( [id] => 131403232835674113 [from] => foo [sent] => 1320163946 [type] => tweet [html] => bar ) [3] => Array ( [id] => 131403230910480384 [from] => foo [sent] => 1320163946 [type] => tweet [html] => bar ) [4] => Array ( [id] => 131403228834299904 [from] => foo [sent] => 1320163945 [type] => tweet [html] => bar ) [5] => Array ( [type] => facebook [from] => foo [html] => bar [sent] => 1320065996 ) [6] => Array ( [type] => facebook [from] => foo [html] => bar [sent] => 1319808945 ) [7] => Array ( [type] => facebook [from] => foo [html] => bar [sent] => 1319789640 ) [8] => Array ( [type] => facebook [from] => foo [html] => bar [sent] => 1319707799 ) [9] => Array ( [type] => facebook [from] => foo [html] => bar [sent] => 1319617295 ) [10] => Array ( [type] => blogger [from] => foo [html] => bar [sent] => 1320157500 ) [11] => Array ( [type] => blogger [from] => foo [html] => bar [sent] => 1320148260 ) ) 

and after that he will have only 5 new ones. However, I want him to have five new ones, but make sure that he has at least one with the type “blogger” and one with the type “facebook” in the final array.

Got this work using Johnny Craig's idea and the following code:

 $output = array(); $output[] = $tweets[0]; $output[] = $items[0]; $output[] = $posts[0]; $feed = array_merge($tweets, $items, $posts); $i = 0; while ($limit > count($output)) { if (!in_array($feed[$i], $output)) { $output[] = $feed[$i]; } $i++; } 

But not quite sure I like it

+4
source share
3 answers

I ended up using the following, based on the idea of ​​@Johnny Craig.

 if ( !empty($tweets) ) $output[] = $tweets[0]; if ( !empty($items) ) $output[] = $items[0]; if ( !empty($posts) ) $output[] = $posts[0]; $feed = array_merge($tweets, $items, $posts); $i = 0; while ( $limit > count($output) ) { if (!in_array($feed[$i], $output)) { $output[] = $feed[$i]; } $i++; } 

This is the same as above, except that I need to add if (!empty()) bits if (!empty()) there wasn’t a specific type.

+1
source

You can do it like this:

  • Get the first 5 entries
  • check if they are just twitter or not.
  • if so, pull first from the array where type = facebook or blogger

Question: which is faster? Array splitting or iterare through one to search for types.

Edit: An alternative would be to consider your twitter posts, so when repeating through an array that you have, for example, $ twitter = 3, and since then you change the corresponding parameter to! = Twitter

+1
source

Checking “at least one record” of each type can lead to several iterations to determine which publication should be replaced for another type of message. Think: if there were messages like {tweet, tweet, tweet, tweet, facebook} in the feed array of feeds, then you need a “blogger” post, but just popping up the oldest post and clicking on the new post will not be enough; applying this logic would leave us with messages like {tweet, tweet, tweet, tweet, blogger}. Instead, applying a limit of "no more than three posts" of any given type ensures that the final array of feeds will never be flooded with a single message type. Sort of:

 // Get our first three newest posts, tracking their types for( $count["blogger"] = $count["facebook"] = $count["tweet"] = $p = 0 ; $p < 3 ; $p++ ) { // Add the newest post $finalFeedArray[$p] = $aggregatedFeedsArray[$p]; // Increment the count for that post type $count[ $finalFeedArray[$p]["type"] ] += 1; } // Fill the remaining two slots for( $q = 3 ; count( $finalFeedArray ) < 5 ; $q++ ) { // If the next newest post type does not occur three or more times if( $count[ $aggregatedFeedsArray[$q]["type"] ] < 3 ) { // Add the post $finalFeedArray[] = $aggregatedFeedsArray[$q]; // Increment the count for that post type $count[ $aggregatedFeedsArray[$q]["type"] ] += 1; } } 

EDIT:. Like zcei , there may be a problem with adding message types in the future. Consider this less explicit option, which abstracts the message types:

 // Type counting array $count = array(); // Get our first three newest posts, tracking their types for( $p = 0 ; $p < 3 ; $p++ ) { // Add the newest post $finalFeedArray[$p] = $aggregatedFeedsArray[$p]; // Increment the count for that post type $count[ $finalFeedArray[$p]["type"] ] += 1; } // Fill the remaining two slots for( $q = 3 ; count( $finalFeedArray ) < 5 ; $q++ ) { // If the next newest post type does not occur three or more times if( $count[ $aggregatedFeedsArray[$q]["type"] ] < 3 ) { // Add the post $finalFeedArray[] = $aggregatedFeedsArray[$q]; // Increment the count for that post type $count[ $aggregatedFeedsArray[$q]["type"] ] += 1; } } 

It is important to note that while types are abstracted, this still limits us to 5 max messages. If you want to create a more reliable solution for building feeds, let me know directly, but any of the above should satisfy your current needs.

0
source

Source: https://habr.com/ru/post/1379166/


All Articles