我想在Twitter上为我们的客户发布服务器消息 不幸的是,Twitter只允许发布140个或更少的Chars。这是一种耻辱。
现在,我必须编写一个算法,将来自服务器的不同消息连接在一起,但将它们缩短为最多140个字符。
这很棘手。
static string concatinateStringsWithLength(string[] strings, int length, string separator) {
// This is the maximum number of chars for the strings
// We have to subtract the separators
int maxLengthOfAllStrings = length - ((strings.Length - 1) * separator.Length);
// Here we save all shortenedStrings
string[] cutStrings = new string[strings.Length];
// This is the average length of all the strings
int averageStringLenght = maxLengthOfAllStrings / strings.Length;
// Now we check how many strings are longer than the average string
int longerStrings = 0;
foreach (string singleString in strings)
{
if (singleString.Length > averageStringLenght)
{
longerStrings++;
}
}
// If a string is smaller than the average string, we can more characters to the longer strings
int maxStringLength = averageStringLenght;
foreach (string singleString in strings)
{
if (averageStringLenght > singleString.Length)
{
maxStringLength += (int)((averageStringLenght - singleString.Length) * (1.0 / longerStrings));
}
}
// Finally we shorten the strings and save them to the array
int i = 0;
foreach (string singleString in strings)
{
string shortenedString = singleString;
if (singleString.Length > maxStringLength)
{
shortenedString = singleString.Remove(maxStringLength);
}
cutStrings[i] = shortenedString;
i++;
}
return String.Join(separator, cutStrings);
}
此算法有效,但不是很优化。 它使用的字符少于实际使用的字符数。
这个问题的主要问题是变量longerStrings
相对于maxStringLength
,而后退。
这意味着如果我更改longerStrings
,maxStringLength
会更改,依此类推,依此类推。
我必须做一个while循环并执行此操作直到没有任何更改,但我不认为这对于这么简单的情况是必要的。
你能告诉我如何继续吗?
或者可能已经存在类似的东西?
谢谢!
我从服务器获得的消息如下所示:
等等。
我想要的是将字符串与分隔符连接起来,在本例中为分号 应该有最大长度。首先应缩短长串。
这是一个主题
这是身体,有点lon ...
2013年2月25日
这是一个... ...
这是...
2013年2月25日
我认为你明白了;)
答案 0 :(得分:1)
比你的慢五倍(在我们的简单例子中)但是应该使用最大可用空间(没有关键值检查):
static string Concatenate(string[] strings, int maxLength, string separator)
{
var totalLength = strings.Sum(s => s.Length);
var requiredLength = totalLength - (strings.Length - 1)*separator.Length;
// Return if there is enough place.
if (requiredLength <= maxLength)
return String.Concat(strings.Take(strings.Length - 1).Select(s => s + separator).Concat(new[] {strings.Last()}));
// The problem...
var helpers = new ConcatenateInternal[strings.Length];
for (var i = 0; i < helpers.Length; i++)
helpers[i] = new ConcatenateInternal(strings[i].Length);
var avaliableLength = maxLength - (strings.Length - 1)*separator.Length;
var charsInserted = 0;
var currentIndex = 0;
while (charsInserted != avaliableLength)
{
for (var i = 0; i < strings.Length; i++)
{
if (charsInserted == avaliableLength)
break;
if (currentIndex >= strings[i].Length)
{
helpers[i].Finished = true;
continue;
}
helpers[i].StringBuilder.Append(strings[i][currentIndex]);
charsInserted++;
}
currentIndex++;
}
var unified = new StringBuilder(avaliableLength);
for (var i = 0; i < strings.Length; i++)
{
if (!helpers[i].Finished)
{
unified.Append(helpers[i].StringBuilder.ToString(0, helpers[i].StringBuilder.Length - 3));
unified.Append("...");
}
else
{
unified.Append(helpers[i].StringBuilder.ToString());
}
if (i < strings.Length - 1)
{
unified.Append(separator);
}
}
return unified.ToString();
}
连接内部:
class ConcatenateInternal
{
public StringBuilder StringBuilder { get; private set; }
public bool Finished { get; set; }
public ConcatenateInternal(int capacity)
{
StringBuilder = new StringBuilder(capacity);
}
}