【问题标题】:How to access "two" in (("one" . "two")) in elisp如何在 elisp 中访问 (("one" . "two")) 中的 "two"
【发布时间】:2014-09-24 14:39:33
【问题描述】:

我对 elisp 很陌生,我正在尝试调整一些现有代码。

在循环表(由 orgmode 函数 org-clock-get-table-data 生成)时,我尝试以下操作:

((equal column "Project") (insert (cdr row)))

它在 Messages 缓冲区中产生以下内容:

cond: Wrong type argument: char-or-string-p, (#("Verify CalTime accruals for vacation/sick" 0 41   
(fontified t org-category #("Admin" 0 5 (fontified t org-category "Admin" org-category-position 32    
line-prefix nil wrap-prefix nil ...)) org-category-position 32 line-prefix #("*" 0 1 (face org-
hide)) wrap-prefix #("    " 0 4 (face org-indent)) ...)) nil 30 (("wps" . "Administration")))

我要插入的值是“管理”,所以我试试这个

((equal column "Project") (insert (nth 4 row)))

在小缓冲区中产生以下内容

Wrong type argument, char-or-string-p, (("wps" . "Administration"))

谁能告诉我如何插入字符串“Administration”?

编辑

感谢韦斯和德鲁:

(cdar row)

执行上述操作会产生我之前在 Messages 缓冲区中看到的复杂列表的第一个元素:

Verify CalTime accruals for vaction/sick

row 似乎是一个复杂的列表列表:

((equal column "Project") (insert (car row))); yeilds ^B

((equal column "Project") (insert (cdr row)))
yields:
cond: Wrong type argument: char-or-string-p, (#("Verify CalTime accruals for vacation/sick" 0 41 
(fontified t org-category #("Admin" 0 5 (fontified t org-category "Admin" org-category-position 32 
line-prefix nil wrap-prefix nil ...)) org-category-position 32 line-prefix #("*" 0 1 (face org-
hide)) wrap-prefix #("    " 0 4 (face org-indent)) ...)) nil 30 (("wps" . "Administration")))

我认为上面输出中的每个“#”都代表一个列表项。 (nth 4 row) 给出上面显示的错误输出的事实支持了这一点,并表明这样的事情可能会起作用:

((equal column "Project") (insert (nth 2 (nth 4 row))))
;yeilds wrong type argument, char-or-string-p, nil

所以我可能需要使用一些函数来解码第 4 个列表项......

第 4 个元素是 orgmode 属性,它已分配给我们正在解析的行上的时钟表条目。这个属性列表在我的 .emacs 中定义:

(setq org-global-properties
;; WPS = Web Platform Services.  Time tracking for Google Sheet begun with CalTime Migration
            '(("wps_ALL". 
"Administration
ASG-Consulting
Chanc-Office-Website
")))

【问题讨论】:

  • 令人困惑的是,在您的一个 sn-ps 中以 #(" 开头的 Emacs Lisp 语法实际上 表示一个列表,而是一个具有文本属性的字符串。有关其工作原理的详细信息,请参阅 Emacs Lisp 手册中的 Info 节点“Text Props and Strings”。
  • 为了拆分更复杂的列表结构,我发现cl-destructuring-bindpcase 宏非常有用。 (后者仅存在于 Emacs 24 中)。两者都允许您通过写下其结构的一种模板来提取列表的一部分,因此代码的形状类似于您要查找的数据的形状。
  • 超级有用!谢谢@Jon O。我正在努力学习这些功能。
  • 感谢 Lisp 人!所有这些信息都很有帮助。我选择@Phils 答案是因为(assoc) 是解决方案的关键。对于背景,我正在调整org-clocktable-write-default 以展平数据,以便可以将其导入(CSV)到谷歌表格。 Here's the key line in the diff 包含 (assoc)org-clocktable-write-default 给出了答案。 More code here 有帮助。

标签: emacs elisp org-mode


【解决方案1】:

除了assoc + cdr 组合,您还可以使用assoc-default

ELISP> (assoc-default "one" '(("one" . "two"))) => "two"

【讨论】:

  • 呵呵,我从来不知道这个功能。有用。
【解决方案2】:

请注意,(("wps" . "Administration") ("foo" . "bar")) 形式的列表通常是“alists”,因此您可能需要处理列表中有多个项目的情况。

读取:C-hig (elisp) Association Lists RET
还有:(elisp) Dotted Pair Notation

根据测试所需的相等形式,您可以从带有(assoc)(assq) 的alist 中获取键项。 elisp 中的等价字符串不等于 objects,因此在这种情况下,您需要assoc 而不是assq

结果,你得到了整个(KEY . VALUE) 形式,你像往常一样获得了它的cdr;因此:

(let ((my-alist '(("wps" . "Administration") ("foo" . "bar"))))
  (cdr (assoc "wps" my-alist)))

收益:“管理”

【讨论】:

    【解决方案3】:

    在 elisp 中考虑列表很复杂。直到你做的足够多以至于你不再去想它们。哈哈。但是请阅读car(选择列表中的第一个元素)和cdr(选择其余部分)之类的功能以开始使用。然后,您至少可以通过组合短序列中的字母来链接事物。所以你想要的答案是:

    (cdar row)
    

    【讨论】:

    • 进一步解释:(("wps" . "Administration"))car 是该列表的第一个元素("wps" . "Administration")。而那个缺点的cdr"Administration"
    猜你喜欢
    • 2022-12-01
    • 2023-04-06
    • 2013-09-11
    • 2013-04-23
    • 2022-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多