4

I've been making a combined social media feed class which gets posts from Facebook and blogger and tweets from Twitter. It then combines them into one list for display on a site. The problem is that it's rare to see either of the post types because twitter is a lot more active than the other two.

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

My array contains a bunch of arrays which each have a 'type' value, this is the what I need to test for / have at least one of each.

before splice:

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 it will just have the 5 newest. However I want it to have the five newest but make sure that it has at least one with type 'blogger' and one with type 'facebook' in the final array.

Got it 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 really sure I like it

6
  • @Interstellar_Coder which bit do you want an example of? Commented Nov 1, 2011 at 16:13
  • Give us a sample array of the input before the splicing and after the splicing so we can see the intended result. Commented Nov 1, 2011 at 16:15
  • @Interstellar_Coder added example of array before splice, basically I didn't do this before because it's so long and thought I could explain it... obviously not Commented Nov 1, 2011 at 16:23
  • 2
    have you thought about building one array for each type and pulling your 5 newest from the top of each array? Commented Nov 1, 2011 at 16:27
  • @JohnnyCraig that doesn't work. I can get the first three easily enough (one of each type) but then how do I know what to fill the rest of the spaces with? Commented Nov 1, 2011 at 16:38

3 Answers 3

1

You could do it like that:

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

The question is: what is faster? Splitting the array or iterare through one for finding the types.

Edit: An alternative would be to count you twitter posts, so when iterating through the array you have for e.g. $twitter = 3 and since then you change the matching parameter to != twitter

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

2 Comments

it won't always be twitter that has the most new posts, that's just the most common
ok so you want, not relying to special types, one of all in 5 comments? Ok that changes the situation. So you would have to count each type, that might be very misdesigned
1

I ended up using the following based on @Johnny Craig's idea.

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++;
}

Which is the same as above, except that I needed add in the if (!empty()) bits incase there were none of a certain type .

Comments

0

Checking for "at least one post" of each type could lead to multiple iterations to identify which post should be swapped for a post of a different type. Consider: if the final feed array contained posts of types {tweet,tweet,tweet,tweet,facebook} a "blogger" post would be needed, but simply popping the oldest post and pushing the newest post of the needed would not suffice; applying this logic would leave us with posts of types {tweet,tweet,tweet,tweet,blogger}. Instead, applying a limit of "no more than three posts" of any given type would ensure that the final feed array would never be flooded with one post type. Something like:

// 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's type
  $count[ $finalFeedArray[$p]["type"] ] += 1;
}

// Fill the remaining two slots
for( $q = 3 ; count( $finalFeedArray ) < 5 ; $q++ )
{
  // If the next newest post's 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's type
    $count[ $aggregatedFeedsArray[$q]["type"] ] += 1;
  }
} 

EDIT: As zcei mentions, it could be problematic to add post types in the future. Consider this less-explicit variant that abstracts the post 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's type
  $count[ $finalFeedArray[$p]["type"] ] += 1;
}

// Fill the remaining two slots
for( $q = 3 ; count( $finalFeedArray ) < 5 ; $q++ )
{
  // If the next newest post's 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's type
    $count[ $aggregatedFeedsArray[$q]["type"] ] += 1;
  }
} 

It is important to note that, while the types are abstracted, this still caps us at 5 posts max. If you desire a more robust feed building solution, let me know directly, but either of the above should satisfy your current needs.

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.