Вот мой вопрос:Как разбить строку на заданное количество строк?
Дана строка, которая состоит из разделенных пробелами слов, как я могу разделить, что в N строки (примерно) четной длины, только нарушение на пространствах?
Вот что я собрал из исследования:
Я начал исследовать алгоритмы переноса слов, потому что мне кажется, что это в основном проблема переноса текста. Тем не менее, большинство из того, что я нашел до сих пор (и есть много об обертывании слов), предполагает, что ширина линии является известным входом, а количество строк - результатом. Я хочу наоборот.
Я нашел (очень) несколько вопросов, таких как this, которые кажутся вам полезными. Тем не менее, все они сосредоточены на проблеме как одна из оптимизаций - например, как я могу разбить предложение на заданное количество строк, минимизируя рвение строк или потерянное пустое пространство или что-то в этом роде, и делаю это в линейном (или NlogN или любом другом) времени. Эти вопросы, как правило, остаются без ответа, поскольку оптимизационная часть проблемы относительно «жесткая».
Однако меня не волнует оптимизация. Пока строки (в большинстве случаев) примерно равны, я в порядке, если решение не работает в каждом случае с одним краем или не может быть доказано, что это наименьшая временная сложность. Мне просто нужно решение для реального мира, которое может взять строку и несколько строк (больше 2), и вернуть мне массив строк, которые обычно выглядят довольно ровно.
Вот что я придумал: Я думаю, что у меня есть работоспособный метод для случая, когда N = 3. Я начинаю с первого слова на первой строке, последнего слова на последней строке, а затем итеративно помещаю другое слово в первую и последнюю строки, пока моя общая ширина (измеренная длиной самой длинной линии) перестанет становиться короче , Обычно это работает, но сработает, если ваши самые длинные слова находятся в середине линии, и это не кажется очень обобщаемым для более чем трех строк.
var getLongestHeaderLine = function(headerText) {
//Utility function definitions
var getLongest = function(arrayOfArrays) {
return arrayOfArrays.reduce(function(a, b) {
return a.length > b.length ? a : b;
});
};
var sumOfLengths = function(arrayOfArrays) {
return arrayOfArrays.reduce(function(a, b) {
return a + b.length + 1;
}, 0);
};
var getLongestLine = function(lines) {
return lines.reduce(function(a, b) {
return sumOfLengths(a) > sumOfLengths(b) ? a : b;
});
};
var getHeaderLength = function(lines) {
return sumOfLengths(getLongestLine(lines));
}
//first, deal with the degenerate cases
if (!headerText)
return headerText;
headerText = headerText.trim();
var headerWords = headerText.split(" ");
if (headerWords.length === 1)
return headerText;
if (headerWords.length === 2)
return getLongest(headerWords);
//If we have more than 2 words in the header,
//we need to split them into 3 lines
var firstLine = headerWords.splice(0, 1);
var lastLine = headerWords.splice(-1, 1);
var lines = [firstLine, headerWords, lastLine];
//The header length is the length of the longest
//line in the header. We will keep iterating
//until the header length stops getting shorter.
var headerLength = getHeaderLength(lines);
var lastHeaderLength = headerLength;
while (true) {
//Take the first word from the middle line,
//and add it to the first line
firstLine.push(headerWords.shift());
headerLength = getHeaderLength(lines);
if (headerLength > lastHeaderLength || headerWords.length === 0) {
//If we stopped getting shorter, undo
headerWords.unshift(firstLine.pop());
break;
}
//Take the last word from the middle line,
//and add it to the last line
lastHeaderLength = headerLength;
lastLine.unshift(headerWords.pop());
headerLength = getHeaderLength(lines);
if (headerLength > lastHeaderLength || headerWords.length === 0) {
//If we stopped getting shorter, undo
headerWords.push(lastLine.shift());
break;
}
lastHeaderLength = headerLength;
}
return getLongestLine(lines).join(" ");
};
debugger;
var header = "an apple a day keeps the doctor away";
var longestHeaderLine = getLongestHeaderLine(header);
debugger;
EDIT: Я потащился JavaScript, потому что в конечном счете, я хотел бы решение я могу реализовать на этом языке. Однако это не слишком критично для проблемы, и я бы принял любое решение, которое работает.
EDIT # 2: В то время как производительность не то, что меня больше всего волнует здесь, мне нужно иметь возможность выполнять любое решение, которое я придумываю ~ 100-200 раз, для строк, которые могут быть до ~ 250 длинные символы. Это будет сделано во время загрузки страницы, поэтому его не нужно навсегда. Например, я обнаружил, что пытаясь разгрузить эту проблему в механизм рендеринга, помещая каждую строку в DIV, и игра с размерами не работает, поскольку она (кажется) невероятно дорога для измерения отображаемых элементов.
Не могли бы вы высказать код, который у вас есть до сих пор? –
Не совсем то, что я использую в настоящее время, но реально близко: https://jsfiddle.net/a546ova0/5/ –
@Mojtaba Не хочу, чтобы это было для меня, просто искали новые идеи. Несколько платных программистов уже придумали пустые, так что смотри, чтобы здесь было много инноваций. –