Эй, ребята! Я только что присоединился к сообществу здесь, и я думал, что поделюсь интересной маленькой кроликой, я недавно упал.
Цель
Пару недель назад я выпустил прогрессировать ; Пакет Python для рисования стержней прогресса на командной строке:
apple harvest █▎ 1 / 9 • 11% banana harvest ██ 9 / 99 • 9% caramel harvest ███████████████████▉ 100 / 100 • 100%
Пакет делает пару классных вещей, но я собираюсь сосредоточиться на моем подходе к рисованию бара.
Первый выстрел
Мой первоначальный план для бара был просто для расчета количества доступных пространств, затем заполните правильный процент от него с помощью Unicode «Полный блок» ( █
) символ.
Так, например, батончик длины 10 и процент 0,5 (с 0.0 быть 0% и 1.0 быть на 100%) будет выглядеть так:
[█████ ]
Вот какой-то код, который соответствует этому правилу:
from decimal import Decimal EMPTY = " " def make_bar(length: int, pc: Decimal) -> str: """ Returns a string describing a bar "length" characters long and filled to "pc" percent (0.0 to 1.0). """ render = list(EMPTY * length) # Percentage of the length that each element represents: element_pc = Decimal(1) / length for index in range(length): # Take a slice of the percentage for this element: block_pc = (pc - (index * element_pc)).min(element_pc) # Calculate how full this block needs to be: block_fill_pc = (1 / element_pc) * block_pc # Add an appropriate character to the render: render[index] = make_char(block_fill_pc) return "".join(render) def make_char(pc: Decimal) -> str: """ Gets a character that represents "pc" percent (0.0 - 1.0). """ FULL_BLOCK = 0x2588 return EMPTY if pc < Decimal(0.5) else chr(FULL_BLOCK)
Итак, скажем, я хочу нарисовать батончик длиной 3 и процент 0,7 Отказ Внутри make_bar. ()
:
оказывать
устанавливается в список из 3 пробелов.element_pc
установлен на 0,33 , поскольку каждый элемент в списке представляет 33% барной зоны.В итерации
индекс
:block_pc
Установлено на количество полоса, которая будет описана первым блоком. Расчет для этого(В процентах полного бара - процент, уже отображаемый предыдущими индексами) .min (максимальный процент, который может представлять каждый блок)
. Что.min.min (...)
мешает нам отказаться от большего количества, чем мы можем жевать; Каждый блок может описать только столько, сколько его максимум, и любые остатки должны быть описаны последующими блоками. Итак,block_pc
установлен на(0,7 - (0 * 0,33)). Мин (0,33)
или 0,33 Отказblock_fill_pc
устанавливается на процент полной нессы этого блока. Каждый блок представляет 0,33 площади иblock_pc
это 0,33 Так что этот блок должен быть 1.0 (100%) полный.- Мы передаем это 1.0 к
make_char ()
и – поскольку1,0> 0,5
– Мы получаем полный блок Unicode.
В итерации
индекс
:block_pc
Установлено на сумму полоса, который будет описан вторым блоком:(0,7 - (1 * 0,33)). Мин (0,33)
или 0,33 Отказblock_fill_pc
устанавливается на процент полной нессы этого блока. Каждый блок представляет 0,33 площади иblock_pc
это 0,33 Так что этот блок должен быть 1.0 полный.- Мы передаем это 1.0 к
make_char ()
и – поскольку1,0> 0,5
– Мы получаем полный блок Unicode.
В итерации
индекс
:block_pc
Установлено на количество полоса, которая будет описана третьим блоком:(0,7 - (2 * 0,33)). Min (0,33)
или 0,04 Отказblock_fill_pc
устанавливается на процент полной нессы этого блока. Каждый блок представляет 0,33 площади иblock_pc
это 0,04 Так что этот блок должен быть 0,12 полный.- Мы передаем это 0,12 к
make_char ()
и – поскольку0,12 <0,5
– Мы получаем пустое пространство назад.
- Наконец, мы присоединяемся к
оказывать
Вместе, чтобы получить бар в виде строки, содержащей два полных блока Unicode и пустой строки.
Мы можем запустить это для ряда рядов постоянно растущих процентов с таким кодом:
if __name__ == "__main__": """ Print a series of rows with ever-increasing percentages. """ ROW_COUNT = 11 iteration_pc = (Decimal(1) / (ROW_COUNT - 1)) for index in range(ROW_COUNT): pc = iteration_pc * index bar = make_bar(length=6, pc=pc) print(f"{pc:0.2f}: [{bar}]")
И вот наш красивый вывод!
0.00: [ ] 0.10: [█ ] 0.20: [█ ] 0.30: [██ ] 0.40: [██ ] 0.50: [███ ] 0.60: [████ ] 0.70: [████ ] 0.80: [█████ ] 0.90: [█████ ] 1.00: [██████]
Ну, не так красивая
Это Хорошо , но это не Красивая Отказ Согласно этим барам, 0,10 и 0.20 такие же, как есть 0,30 и 0,40 , 0,60 и 0,70 и 0,80 и 0,90 Отказ
Не было бы неплохо добавить еще немного гранулярности?
Не было бы неплохо, если бы мы могли нарисовать блоки, которые были меньше, чем ширина полного персонажа?
Ну, мы можем!
В то время как персонаж Unicode 0x2588
Представляет полный блок, есть также серия символов Unicode, которые описывают восьмые блока:
0x2588. | █ | Левый 8/8 (полный блок) |
0x2589. | ▉ | Оставил 7/8 |
0x258a. | ▊ | Оставил 6/8 |
0x258b. | ▋ | Оставил 5/8 |
0x258c. | ▌ | Оставил 4/8 |
0x258d. | ▍ | Оставил 3/8 |
0x258e. | ▎ | Оставил 2/8 |
0x258f. | ▏ | Оставил 1/8 |
Сделай это красивым!
Итак, давайте обновим make_char ()
Чтобы вернуть один из этих символов вместо двоичного «ON или OFF» для каждого блока:
from math import ceil def make_char(pc: Decimal) -> str: """ Gets a character that represents "pc" percent (0.0 - 1.0). """ eighths = ceil(pc * 8) return chr(0x2590 - eighths) if eighths > 0 else EMPTY
По сути, мы можем рассчитать, сколько восьмых процентов состоит в том, чтобы умножить его на 8:
- 0,000 (
0.000 * 8
) это 0 восьмые. - 0,125 (
0.125 * 8
) IS 1 восьмой. - 0.250 (
0,250 * 8
) Это 2 восьмые. - 0,375 (
0,375 * 8
) это 3 восьмые. - 0.500 (
0.500 * 8
) это 4 восьмые. - 0.625 (
0,625 * 8
) это 5 восьмые. - 0.750 (
0,750 * 8
) это 6 восьмые. - 0.875 (
0,875 * 8
) это 7 восьмые. - 1.000 (
1.000 * 8
) это 8 восьмые.
Когда мы знаем, сколько восьмых процентов, мы можем вычесть, что компенсировать от 0x2590
Чтобы получить правильный символ:
0x2590 -
(1/8)0x2590 -
(2/8)0x2590 -
(3/8)0x2590 -
(4/8)0x2590 -
(5/8)0x2590 -
(6/8)0x2590 -
(7/8)0x2590 -
(8/8)
Теперь, если мы запустим код с обновленным make_char ()
Функция:
0.00: [ ] 0.10: [▋ ] 0.20: [█▎ ] 0.30: [█▉ ] 0.40: [██▌ ] 0.50: [███ ] 0.60: [███▋ ] 0.70: [████▎ ] 0.80: [████▉ ] 0.90: [█████▌] 1.00: [██████]
Та-да! Каждая ряд теперь имеет Многое Более точный бар!
Фактически, с одним быстрым изменением скрипта мы можем создать строку для каждого возможного частичного блока:
if __name__ == "__main__": """ Print a series of rows with ever-increasing percentages. """ LENGTH = 2 ROW_COUNT = (8 * LENGTH) + 1 iteration_pc = (Decimal(1) / (ROW_COUNT - 1)) for index in range(ROW_COUNT): pc = iteration_pc * index bar = make_bar(length=LENGTH, pc=pc) print(f"{pc:0.2f}: [{bar}]")
0.00: [ ] 0.06: [▏ ] 0.12: [▎ ] 0.19: [▍ ] 0.25: [▌ ] 0.31: [▋ ] 0.38: [▊ ] 0.44: [▉ ] 0.50: [█ ] 0.56: [█▏] 0.62: [█▎] 0.69: [█▍] 0.75: [█▌] 0.81: [█▋] 0.88: [█▊] 0.94: [█▉] 1.00: [██]
Теперь, кто сказал, что инструменты командной строки не могут быть красивыми?
Рекомендуемая Фото Уэсли Тинги. на Бессмысленно .
Оригинал: “https://dev.to/cariad/drawing-blocks-on-the-command-line-with-python-3pn7”