字符串连接/缩短算法
本文关键字:算法 连接 字符串 | 更新日期: 2023-09-27 18:01:04
我想在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循环,直到没有变化为止,但我认为对于这样一个简单的情况来说,这是没有必要的。
你能给我一个如何继续的线索吗?
或者可能已经存在类似的东西了?
谢谢!
编辑
我从服务器收到的消息如下:
- 消息
- 主题
- 日期
- 车身
- 消息
- 主题
- 日期
- 车身
等等。
我想要的是用分隔符连接字符串,在本例中是分号
应该有一个最大长度。长字符串应该先缩短。
示例
这是一个主题
这是身体,有点长
2013年2月25日
这是一个…
这是
2013年2月25日
我想你已经明白了;(
比您的速度慢五倍(在我们的简单示例中(,但应使用最大可用空间(无关键值检查(:
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);
}
}