1

Let's say I have an array of Twitter account names:

string = %w[example1 example2 example3 example4 example5 example6 example7 example8 example9 example10 example11 example12 example13 example14 example15 example16 example17 example18 example19 example20]

And a prepend and append variable:

prepend = 'Check out these cool people: '
append = ' #FollowFriday'

How can I turn this into an array of as few strings as possible each with a maximum length of 140 characters, starting with the prepend text, ending with the append text, and in between the Twitter account names all starting with an @-sign and separated with a space. Like this:

tweets = ['Check out these cool people: @example1 @example2 @example3 @example4 @example5 @example6 @example7 @example8 @example9 #FollowFriday', 'Check out these cool people: @example10 @example11 @example12 @example13 @example14 @example15 @example16 @example17 #FollowFriday', 'Check out these cool people: @example18 @example19 @example20 #FollowFriday']

(The order of the accounts isn't important so theoretically you could try and find the best order to make the most use of the available space, but that's not required.)

Any suggestions? I'm thinking I should use the scan method, but haven't figured out the right way yet.

It's pretty easy using a bunch of loops, but I'm guessing that won't be necessary when using the right Ruby methods. Here's what I came up with so far:

# Create one long string of @usernames separated by a space
tmp = twitter_accounts.map!{|a| a.insert(0, '@')}.join(' ')
# alternative: tmp = '@' + twitter_accounts.join(' @')

# Number of characters left for mentioning the Twitter accounts
length = 140 - (prepend + append).length

# This method would split a string into multiple strings
# each with a maximum length of 'length' and it will only split on empty spaces (' ')
# ideally strip that space as well (although .map(&:strip) could be use too) 
tweets = tmp.some_method(' ', length)

# Prepend and append
tweets.map!{|t| prepend + t + append}

P.S. If anyone has a suggestion for a better title let me know. I had a difficult time summarizing my question.

2
  • 2
    I would never have thought that you'd need to solve a knapsack problem (or rather subset-sum) to write a twitter bot. :P Commented Apr 19, 2013 at 20:56
  • Hehe. Just to clarify I'm not randomly spamming people with this bot. Throughout the week I blog about a few startup companies (~3/day) and I figured I'd mention their Twitter accounts at the end of the week as my followers are interested in it, and it's additional exposure for these companies as well. Commented Apr 20, 2013 at 11:40

2 Answers 2

3

The String rindex method has an optional parameter where you can specify where to start searching backwards in a string:

arr = %w[example1 example2 example3 example4 example5 example6 example7 example8 example9 example10 example11 example12 example13 example14 example15 example16 example17 example18 example19 example20]
str = arr.map{|name|"@#{name}"}.join(' ')
prepend =  'Check out these cool people: '
append = ' #FollowFriday'
max_chars = 140 - prepend.size - append.size
until str.size <= max_chars do
  p str.slice!(0, str.rindex(" ", max_chars))
  str.lstrip! #get rid of the leading space
end
p str unless str.empty?
Sign up to request clarification or add additional context in comments.

1 Comment

Hadn't considered using slice! and rindex. I've marked Nevir's answer as the accepted one because he was a bit faster and includes the prepend and append texts, but I really appreciate your help as well. Thanks!
1

I'd make use of reduce for this:

string = %w[example1 example2 example3 example4 example5 example6 example7 example8 example9 example10 example11 example12 example13 example14 example15 example16 example17 example18 example19 example20]
prepend = 'Check out these cool people:'
append = '#FollowFriday'

# Extra -1 is for the space before `append`
max_content_length = 140 - prepend.length - append.length - 1

content_strings = string.reduce([""]) { |result, target|
  result.push("") if result[-1].length + target.length + 2 > max_content_length
  result[-1] += " @#{target}"

  result
}

tweets = content_strings.map { |s| "#{prepend}#{s} #{append}" }

Which would yield:

"Check out these cool people: @example1 @example2 @example3 @example4 @example5 @example6 @example7 @example8 @example9 #FollowFriday"
"Check out these cool people: @example10 @example11 @example12 @example13 @example14 @example15 @example16 @example17 #FollowFriday"
"Check out these cool people: @example18 @example19 @example20 #FollowFriday"

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.