【问题标题】:Calculate the target size to truncate to fit strings inside a specific size计算要截断的目标大小以适合特定大小内的字符串
【发布时间】:2021-08-05 06:41:23
【问题描述】:

问题

我正在编写一个程序来在控制台中显示标签(字符串),我需要将它们放在特定的宽度内。当它们的总长度太大时,我需要截断一些标签。我正在寻找一种有效的算法来计算要截断的所有字符串的最大大小。

例如,假设我们有 3 个标签要显示,总可用大小为 12 个字符。以下代码块显示了如何将它们放入可用空间中。 (在实际情况中我们还需要它们之间的分隔符,但为简单起见,此处省略。)

The tags:
 11111         5 chars wide
 2222222       7 chars
 333           3 chars

The space:
|------------| 12 chars

Not truncated:
 111112222222333   5+7+3 = 15 chars, too long

Truncate every tag to 4 chars:
 11112222333   4+4+3 = 11 chars, fits

同样,如果空格长度为 13 个字符,则截断大小为 5 个字符:

|-------------|
 1111122222333  5+5+3 = 13 chars, fits

我目前的解决方案

我目前使用一种简单的方法来解决这个问题。这是伪代码:

// the input
tags = [...]
target_width = ...

tag_widths = tags.map(x => x.width).sort()
total_width = tag_width.sum()

truncated_count = 0
truncate_to = tag_widths[0]

// list of items
// v      | <- truncation line
// *******| 
// *****  |
// ***    |

while true {
  // find the next group of tags with the same length
  //
  //      |
  // ******* <-
  // *****|
  // ***  |
  truncated_count += 1
  while truncated_count < tags.length 
        && tag_widths[truncated_count] == truncate_to {
    truncated_count += 1
  }
  // new_truncate_to is the width of the next group
  new_truncate_to = tag_widths[truncated_count] or 0 if truncated_count > tags.length
  
  // calculate the length after truncating all of them
  //
  //      |
  // *****|-- 
  // *****|
  // ***  |
  new_total_width = total_width - truncated_count * (new_truncate_to - truncate_to)

  if new_total_width <= target_width {
    // the target length is between truncate_to and new_truncate_to
    //       |
    // ******|- 
    // ***** |
    // ***   |
    new_truncate_to += floor((target_width - new_total_width) / truncated_count)
    truncate_to = new_truncate_to
    break
  } else {
    // the current truncation is not enough
    total_width = new_total_width
    truncate_to = new_truncate_to
  }
}

// the result
truncate_to

有没有更高效的算法?

【问题讨论】:

    标签: arrays string algorithm


    【解决方案1】:

    我无法完全理解您的代码,但我提出了一种更有效的算法。

    大部分成本是宽度的初始排序 O(n*log n),然后其余的通过对数组的单次传递完成。

    伪代码:

    let remainingwidth = total available width
    sort tags array by width
    for i=0, i<tags.length; i=i+1
       let avg_avail_width = remainingwidth / (tags-length - i)  //Integer division, rounded down
       if tags[i].width > avg_avail_width
          tags[i].width = avg_avail_width
       end if      
       remainingwidth -= tags[i].width
    end for each
    

    请注意,如果可用宽度不能均匀分布(例如,总宽度 20,标签宽度 [3,7,8,9], 20-3 = 17 所以我们不能让剩余标签的宽度相等)此策略将额外的空间分配给原始宽度最长的标签。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-30
      • 2013-11-16
      • 2022-11-12
      • 1970-01-01
      相关资源
      最近更新 更多