Добавление элементов карты для среза в последовательном порядке

#string #loops #go

# #строка #циклы #Вперед

Вопрос:

Я работаю над функцией переноса текста. Я хочу, чтобы он разбивал длинную строку текста на строковые фрагменты с максимальной длиной символов. У меня это в основном работает. Однако иногда слова располагаются не по порядку.

Это происходит, когда за длинным словом следует короткое слово. Я полагаю, что программа видит, что более длинное слово не поместится в строке, поэтому она пропускает это слово и добавляет следующее подходящее слово.

Поскольку это текст, слова должны располагаться в правильном порядке. Как я могу заставить цикл добавлять слова только в правильном порядке?

Фактический объем производства:

 []string{" Go back out of the hotel entrance and your is", " room on lower ground a private street", " entrance."}
 

Ожидаемый результат:

 []string{" Go back out of the hotel entrance and your", " room is on lower ground a private street", " entrance."}
 

Это то, что у меня есть до сих пор.

Ссылка: https://play.golang.org/p/YsCWoM9hQJV

 package main

import (
    "fmt"
    "strings"
)

func main() {
    directions := "Go back out of the hotel entrance and your room is on the lower ground a private street entrance."

    ws := strings.Split(directions, " ")
    neededSlices := strings.Count(directions, "") / 48
    if strings.Count(directions, "")%48 != 0 {
        neededSlices  
    }
    ls := make([]string, neededSlices, neededSlices)

    keys := make(map[string]bool)
    for i := 0; i < len(ls); i   {
        for _, v := range ws {
            if _, ok := keys[v]; !ok {
                if strings.Count(ls[i], "") strings.Count(v, "") <= 48 {
                    ls[i] = ls[i]   " "   v
                    keys[v] = true
                }
            }
        }
    }

    fmt.Printf("%#v", ls)

}
 

Комментарии:

1. Я понимаю перенос текста, но почему вы удаляете повторяющиеся слова, требуется ли это?

2. Позвольте мне объяснить, как вы вычисляете количество строк, прежде чем удалять повторяющиеся слова; Это путаница, поэтому я хочу немного больше контекста

3. Я не заметил, что повторяющиеся слова были удалены. Еще один недостаток. Спасибо, что указали на это.

4. Как вы думаете, что делает карта

5. ДА. Я только что понял, что карта может содержать только одно значение для каждого ключа, поэтому дубликаты удаляются.

Ответ №1:

Я думаю, что это простая реализация того, что вам нужно

 package main

import (
    "fmt"
    "strings"
)

func main() {
    directions := "Go back out of the hotel entrance and your room is on the lower ground a private street entrance."

    ws := strings.Split(directions, " ")
    
    sl := []string{""}
    i := 0
    
    for _,word := range ws {
        if (len(sl[i])   len(word)   1) >=48 {
            i  
            sl = append(sl, "")
        }
        sl[i]  = " "   word
    }
    

    fmt.Printf("%#v", sl)

}
 

Ссылка: https://play.golang.org/p/7R2TS6lv4Tm

Комментарии:

1. Я знал, что должен быть простой способ сделать это, но я не мог до конца разобраться в этом. Спасибо.

Ответ №2:

Первая проблема, которую я замечаю, — это ваше использование карты. Карта может содержать ключ только один раз. Из-за этого ваш код будет содержать каждое слово только один раз в одном из выходных фрагментов.

Вторая проблема заключается в том, что вы повторяете итерацию по всему массиву ws для каждой итерации среза ls. Я полагаю, вы пытались обойти эту проблему с помощью карты?

Решением было бы выполнить итерацию только один раз по ws и присвоить слова индексу в ls.

Также обратите внимание, что строки.Count возвращает количество символов (точек Юникода) в строке плюс 1.

Кстати, ваш код также добавляет пробел в начале каждой строки в срезе. Я не уверен, предназначено ли это (ваш ожидаемый результат соответствует этому). В моем примере решения я отклоняюсь от этого, поэтому мой результат не на 100% соответствует вашему заявленному ожидаемому результату, но я думаю, что это дает более ожидаемый результат.

 package main

import (
    "fmt"
    "strings"
)

func main() {
    directions := "Go back out of the hotel entrance and your hotel room is on the lower ground a private street entrance."

    ws := strings.Split(directions, " ")
    ls := []string{}

    l := 0 // current line length
    i := -1

    for _, v := range ws {
        lv := strings.Count(v, "")-1

        if l == 0 || l lv 1 > 48 {
            i  
            ls = append(ls, v)
            l = lv
            continue
        }
        
        ls[i]  = " "   v
        l  = lv 1
    }

    fmt.Printf("%#v", ls)
}
 

Игровая площадка Go: https://play.golang.org/p/HhdX8RudiXn

Комментарии:

1. Добро пожаловать. Я отредактировал его, чтобы сделать короче. Обратите внимание, что другое решение от Shubham не может обрабатывать входные данные UTF, потому что len() возвращает количество байтов, а не символов. У него также есть проблема с интервалом.

2. Хороший довод. Сейчас я использую только ASCII, и принтер может печатать 48 символов в строке (бумага 80 мм). Честно говоря, я не уверен, совместимо ли устройство с UTF-8. Команды ESCPOS, с которыми он работает, довольно старые.