Руководство SBCL: Запись списков с контролем длины строк
Узнайте, как форматировать и записывать списки списков в файлы в SBCL с контролем длины строк. Изучите техники красивой печати, динамические переменные и пользовательские решения для читаемых выходных файлов.
Как форматировать и записывать списки списков в файл в SBCL с контролируемой длиной строки?
В пакете Common Lisp, который я разрабатываю, я часто работаю со списками списков, где отдельные списки содержат множество элементов. При записи их в файл с помощью (write stream list) полученные строки становятся чрезвычайно длинными и трудными для чтения.
Например, при записи этих данных:
((IT0005204729 4AIM-SICAF AFF FINANC FSMISC EUR 281 106 9.7029 -0.0022 - -
2.85714 5.65861 -11.76471 -37.2166 -32.07547 -35.287365 -165.4584 - - -
-4.69812 0.43549 - -76.98278 -17.01118 -16.69684 3.6809604 -2.9394858
-22.814877 4.75634 -4.0883703 -20.47732 51.963356 83.06184 55.33002 1.6398745
-158.82921 31.904535 -21.005991 -49.310223 - UP 0)
(IT0005440323 4AIM-SICAF-C2CR AFF FINANC FSMISC EUR 281 - 9.7029 -0.0022 - -
2.85714 5.65861 -11.76471 -37.2166 -32.07547 NA -165.4584 - - - -4.69812
0.43549 - -76.98278 -17.01118 -16.69684 - - - - - - - - - - -158.82921 20
-21.005991 -53.2784 - UP 0)
(IT0001233417 A2A AFF UTILIT ELECTU EUR 1.38 13415263 4899.864 0.9599 5.78005
0.08166 -4.54684 -8.24289 13.33333 -6.09427 25.62249 40.853104 52.60864
31.9303 67.94521 3.84002 365 1.20865 9.86191 0.15859 12.20054 4.96296
-2.4322445 3.5466106 20.909727 -3.233147 3.4399962 16.768408 45.12124
27.513227 60.48246 -0.010872668 47.46384 27.35368 -0.6957139 24.707268 2.1667
UP 0))
Какой лучший подход для форматирования вывода так, чтобы каждый список записывался с контролируемой длиной строки для лучшей читаемости? Существуют ли специфические функции SBCL или методы для форматирования больших списков при записи в файлы?
Для форматирования и записи списков списков в файл в SBCL с контролируемой длиной строки следует использовать систему красивого вывода Common Lisp с такими параметрами, как :right-margin, :pretty, или устанавливать динамические переменные, такие как *print-right-margin*. Лучший подход включает использование функции write с аргументами красивого вывода или функции format с соответствующими директивами форматирования для обеспечения читаемой длины строк.
Содержание
- Использование функции Write с красивым выводом
- Динамические переменные для управления выводом
- Подход с использованием функции Format
- Решения для переноса строк
- Полный практический пример
Использование функции Write с красивым выводом
Наиболее прямой подход - использование функции write с ключевыми аргументами красивого вывода. Функция write принимает несколько параметров, контролирующих форматирование списков:
(with-open-file (stream "output.txt" :direction :output :if-exists :supersede)
(write your-list-of-lists :stream stream
:pretty t ; Включить красивый вывод
:right-margin 80 ; Установить правое поле в 80 символов
:escape nil ; Не экранировать специальные символы
:miser-width 20)) ; Использовать miser-стиль, если в пределах 20 символов от правого поля
Согласно Common Lisp HyperSpec, функция write принимает ключевые аргументы, включая :right-margin, :pretty и :miser-width, которые соответствуют динамическим переменным, управляющим поведением красивого вывода.
Динамические переменные для управления выводом
Вы также можете управлять форматированием вывода, устанавливая динамические переменные перед записью:
(let ((*print-pretty* t) ; Включить красивый вывод
(*print-right-margin* 80) ; Установить правое поле в 80 символов
(*print-miser-width* 20)) ; Использовать miser-стиль в пределах 20 символов
(with-open-file (stream "output.txt" :direction :output :if-exists :supersede)
(write your-list-of-lists :stream stream)))
Как объясняется в документации красивого вывода Lisp, правое поле контролируется переменной *print-right-margin*, и красивый вывод автоматически будет вставлять разрывы строк, когда контент превышает этот лимит.
Подход с использованием функции Format
Функция format предоставляет обширные возможности форматирования. Вы можете использовать ее для форматирования списков с контролируемой длиной строки:
(with-open-file (stream "output.txt" :direction :output :if-exists :supersede)
(format stream "~{~{~A~^ ~}~%~}" your-list-of-lists))
Для более сложного форматирования можно использовать директивы format, контролирующие разрывы строк:
(defun write-list-with-controlled-line-length (list stream max-line-length)
"Записать список в поток с контролируемой длиной строки"
(let ((current-line-length 0)
(words (mapcar #'princ-to-string list)))
(dolist (word words)
(let ((word-length (length word)))
(when (> (+ current-line-length word-length 1) max-line-length)
(format stream "~%")
(setf current-line-length 0))
(format stream "~A" word)
(incf current-line-length word-length)
(unless (eq word (car (last words)))
(format stream " ")
(incf current-line-length 1))))))
Решения для переноса строк
Для более точного контроля над разрывами строк можно реализовать собственный перенос строк:
(defun write-list-with-line-wrap (list stream max-line-length)
"Записать список в поток с автоматическим переносом строк"
(let ((current-line 0))
(dolist (item list)
(let* ((item-str (princ-to-string item))
(item-len (length item-str)))
(when (> (+ current-line item-len 1) max-line-length)
(format stream "~%")
(setf current-line 0))
(format stream "~A" item-str)
(incf current-line item-len)
(unless (eq item (car (last list)))
(format stream " ")
(incf current-line 1))))))
Затем можно использовать эту функцию с with-open-file:
(with-open-file (stream "output.txt" :direction :output :if-exists :supersede)
(dolist (sublist your-list-of-lists)
(write-list-with-line-wrap sublist stream 80)
(format stream "~%")))
Полный практический пример
Вот полное решение, обрабатывающее вашу конкретную структуру данных:
(defun write-formatted-lists-to-file (filename list-of-lists &optional (max-line-length 80))
"Записать списки списков в файл с контролируемой длиной строки"
(with-open-file (stream filename
:direction :output
:if-exists :supersede
:external-format :utf-8)
(dolist (list-item list-of-lists)
;; Использовать write с красивым выводом для автоматического форматирования
(write list-item :stream stream
:pretty t
:right-margin max-line-length
:escape nil
:miser-width 20)
;; Добавить новую строку между списками
(format stream "~%")))
Для ваших конкретных примеров данных:
(defvar *sample-data*
'((IT0005204729 4AIM-SICAF AFF FINANC FSMISC EUR 281 106 9.7029 -0.0022 - -
2.85714 5.65861 -11.76471 -37.2166 -32.07547 -35.287365 -165.4584 - - -
-4.69812 0.43549 - -76.98278 -17.01118 -16.69684 3.6809604 -2.9394858
-22.814877 4.75634 -4.0883703 -20.47732 51.963356 83.06184 55.33002 1.6398745
-158.82921 31.904535 -21.005991 -49.310223 - UP 0)
(IT0005440323 4AIM-SICAF-C2CR AFF FINANC FSMISC EUR 281 - 9.7029 -0.0022 - -
2.85714 5.65861 -11.76471 -37.2166 -32.07547 NA -165.4584 - - - -4.69812
0.43549 - -76.98278 -17.01118 -16.69684 - - - - - - - - - - -158.82921 20
-21.005991 -53.2784 - UP 0)
(IT0001233417 A2A AFF UTILIT ELECTU EUR 1.38 13415263 4899.864 0.9599 5.78005
0.08166 -4.54684 -8.24289 13.33333 -6.09427 25.62249 40.853104 52.60864
31.9303 67.94521 3.84002 365 1.20865 9.86191 0.15859 12.20054 4.96296
-2.4322445 3.5466106 20.909727 -3.233147 3.4399962 16.768408 45.12124
27.513227 60.48246 -0.010872668 47.46384 27.35368 -0.6957139 24.707268 2.1667
UP 0)))
;; Запись с контролируемой длиной строки
(write-formatted-lists-to-file "formatted_output.txt" *sample-data* 80)
Если вам нужен более точный контроль над форматированием, вы также можете использовать красивый вывод напрямую с pprint:
(with-open-file (stream "output.txt" :direction :output :if-exists :supersede)
(let ((*print-right-margin* 80))
(dolist (item list-of-lists)
(pprint item stream)
(format stream "~%"))))
Эти подходы обеспечат запись списков в файлы с контролируемой длиной строк, делая их гораздо более читаемыми. Подход с использованием красивого вывода обычно предпочтительнее, так как он автоматически обрабатывает отступы и разрывы строк интеллектуально.
Источники
- Руководство пользователя SBCL 2.5.10 - Ввод-вывод файлов
- Common Lisp HyperSpec - Функция Write
- Документация красивого вывода Lisp
- Stack Overflow - Запись списков в файлы с контролируемой длиной
- Common Lisp Cookbook - Файлы и каталоги
Заключение
Для эффективного форматирования и записи списков списков в файлы в SBCL с контролируемой длиной строки:
- Используйте систему красивого вывода с функцией
writeи параметром:right-marginдля автоматического интеллектуального форматирования - Устанавливайте динамические переменные, такие как
*print-right-margin*и*print-pretty*, для управления форматированием вывода - Рассмотрите возможность использования переноса строк для более точного контроля, когда красивый вывод недостаточен
- Используйте директивы
formatдля конкретных требований форматирования и контроля разрывов строк - Тестируйте с вашими реальными данными, чтобы настроить параметры, такие как
:miser-widthи поля длины строки
Подход с использованием красивого вывода обычно является наиболее надежным и поддерживаемым решением для обработки сложных вложенных структур данных при обеспечении читаемых выходных файлов.