我想在 Twitter 上为我们的客户发布服务器消息。
不幸的是,Twitter 只允许发布 140 个字符或更少。这是一种耻辱。
现在,我必须编写一个算法,将来自服务器的不同消息连接在一起,但将它们缩短到最多 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 循环并执行此操作,直到没有任何更改为止,但我认为对于这种简单的情况没有必要这样做。
你能告诉我如何继续吗?
或者也许已经存在类似的东西?
谢谢!
编辑
我从服务器得到的消息是这样的:
- 留言
- 主题
- 日期
- 正文
- 留言
- 主题
- 日期
- 正文
等等。
我想要的是用分隔符连接字符串,在本例中是分号。
应该有一个最大长度。应先缩短长字符串。
例子
这是一个主题
这是本体,有点长……
25.02.2013
这是一个...
这是……
25.02.2013
我想你明白了 ;)
最佳答案
比你的慢五倍(在我们的简单示例中)但应该使用最大可用空间(不检查临界值):
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();
}
和ConcatenateInternal:
class ConcatenateInternal
{
public StringBuilder StringBuilder { get; private set; }
public bool Finished { get; set; }
public ConcatenateInternal(int capacity)
{
StringBuilder = new StringBuilder(capacity);
}
}
关于c# - 字符串连接/缩短算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15066833/