我有一个函数可以对12行CSV数据执行操作。
这12行是从一个更大的CSV文件中读取的。当它完成时,该过程将在随后的12行批处理中再重复5次。
(defun main ()
(send-actions 0 12 "client-one")
(send-actions 12 24 "client-two")
....
(send-actions 60 72 "client-six")
...)
(defun send-actions (start end account)
(check-upload-send (subseq (read-csv #P"~/Desktop/data.csv") start end) account))
(defun check-upload-send (table account)
(function to check for duplicates....)
(function to perform action 1....)
...)
这真的很有效,大多数时候。
它经常会抛出一个重复的错误,这是因为它将重新读取第25行(这是运行(send-actions 24 36 "client-three")
的第一项)。
有没有更好的功能或方法来阅读一组csv行并在其上执行操作?具有移动到下一批12行的能力?
谢啦,谢啦
注意-read-csv
来自cl-csv
1条答案
按热度按时间gijlo24d1#
让我们使用这个
/tmp/test.csv
文件:(我有6个条目,按2行分组)
当使用带有
row-fn
参数的cl-csv:read-csv
时,行不会被收集,而是给到一个回调函数,我知道当有太多级别的回调时,有时会被称为“回调地狱”,但我倾向于喜欢这种方法,因为它很容易编写,而且,你只需要读取文件一次,并且不需要在内存中存储不确定数量的数据(在这里可以忽略不计)。例如,我可以编写一个高阶函数
make-group-reader
来创建一个闭包,它以size
大小的组收集行,然后在该组完成时调用另一个回调group-fn
。注意,如果最后一个片段不完整,则不会调用组回调(但如果需要,您可以修改一些东西):默认情况下,
sharedp
参数为T,并直接将内部向量提供给回调函数。如果愿意,可以先用COPY-SEQ
复制向量,将其设置为NIL。然后,我将进行另一个回调,为每个传入组从客户端列表中弹出项目,用于将组与客户端关联起来,并调用另一个函数:
让我们定义一个客户端示例列表:
此外,
debug-client-cb
用于测试:然后,下面的调用按2对行进行分组,并使用关联的客户机为每个组调用调试函数。
您可以将事情简化一点,如下所示:
并将
(make-my-csv-reader)
作为:row-fn
传递。我很好奇为什么会使用这种方法而不是subseq方法?主要原因是因为数据只读一次吗?
是的,我尽量避免在处理数据时加载整个文件,将数据视为值流并以增量方式构建结果比需要不确定内存量的步骤更健壮。
在某些情况下,这不是最合理的方法,因为一次读取整个文件并处理它更容易/更快。
还有其他原因吗?
我喜欢把复杂性分解成层次的方式:首先对项目进行分组,然后处理它们,等等,并且可以在流水线中添加任何中间功能以进行调试,等等。
另外,回调函数是闭包,可以用来控制处理结束的时间,我可以提前从闭包返回,而不是阅读每一行并处理它们: