I'm trying to create a function in lisp that receives two lists and distributes their values into a new list. I need to get the values of the first list and apply to every element of the second.
For example :
(funcA '("A" "B" "C") '("D" "E" "F"))
And returns something like this:
((("A" "B" "C") . "D")
(("A" "B" "C") . "E")
(("A" "B" "C") . "F"))
The thing is: I'm not able to get the car value.
Here is my code:
(defun funcA (list1 list2)
(if (null list1)
nil
(if (null list2)
nil
(cons (cons (cdr list1) (car list2))
(funcA list1 (cdr list2))))))
The function above returns me :
((("B" "C") . "D")
(("B" "C") . "E")
(("B" "C") . "F"))
I do not get the point of the use of the function funcA. but if you say that it should work as follows:
For example :
(funcA '("A" "B" "C") '("D" "E" "F"))
And returns something like this:
((("A" "B" "C") . "D") (("A" "B" "C") . "E") (("A" "B" "C") . "F"))
your code is near to the solution, but you need to remove un lisp procedure like this:
CL-USER> (defun funcA (list1 list2)
(if (null list1 )
nil
(if ( null list2)
nil
(cons (cons list1 (car list2 ))
(funcA list1 (cdr list2))))))
FUNCA
CL-USER> (funcA '("A" "B" "C") '("D" "E" "F"))
((("A" "B" "C") . "D") (("A" "B" "C") . "E") (("A" "B" "C") . "F"))
you can see that the last line is equal to what tou want
((("A" "B" "C") . "D") (("A" "B" "C") . "E") (("A" "B" "C") . "F"))
the problem was this expression:
(cons (cons (cdr list1 ) (car list2 )) => should be (cons (cons list1 (car list2 ))
Why not just
(defun funcA (list1 list2)
(mapcar (lambda (el) (cons list1 el)) list2))
?
You could use the loop macro. The "collect" keyword causes loop to zip up the result and return it as a list:
(defun funcA (list1 list2)
(loop for i in list2
collect (cons list1 i)))
Note the placement of list1 and list2 in the above code.
Calling it in this fashion:
(funca '("a" "b" "c") '("d" "e" "f"))
Returns:
((("a" "b" "c") . "d") (("a" "b" "c") . "e") (("a" "b" "c") . "f"))
Related
I am trying to code a function that will let me input a list, and it will produce a list of lists. Each list in the product will contain i+1 duplicates of the what was in index i of the original list.
So something like (expand (list "a" "b" "c")) will give me (list (list "a") (list "b" "b") (list "c" "c" "c")).
I am using Racket Beginning Student with List Abbreviations, and I am not allowed to use the "make-list" function.
Write helper function with new argument (i = number of duplicates) and use function make-list for repeating given element i times (or write your own version of make-list):
(define (my-make-list i elem)
(if (<= i 0) '()
(cons elem (my-make-list (- i 1) elem))))
(define (expand-help lst i)
(if (null? lst) '()
(cons (my-make-list i (car lst))
(expand-help (cdr lst) (+ i 1)))))
(define (expand lst)
(expand-help lst 1))
Example:
> (expand (list "a" "b" "c"))
(list (list "a") (list "b" "b") (list "c" "c" "c"))
I am trying to make a function that returns true or false if a list is in order. I can't figure out how to make it recursive. I keep getting error messages on the last line: define: expected only one expression for the function body, but found 1 extra part
(check-expect (is-sorted? (list)) true)
(check-expect (is-sorted? (list "A")) true)
(check-expect (is-sorted? (list "B" "A")) false)
(check-expect (is-sorted? (list "A" "B")) true)
(check-expect (is-sorted? (list "A" "C" "B")) false)
(check-expect (is-sorted? (list "A" "B" "C")) true)
(define (is-sorted? lst)
(cond
((empty-list? lst) true)
((= (length lst) 1) true) ;return true if there is only one element.
((string<? (first lst) second lst) true) ;If the first element is smaller than the second
;return true.
(else (is-sorted? (rest lst))))) ;do the above steps on the rest of the elements in the list.
Notice that you're not considering the case when the procedure should return false, and that you exit prematurely when you find that an element is sorted with respect to the next element (you need to keep iterating! it's just one match, what about the others?). The solution is simple, just negate the condition for this case and ask if it's not sorted return false. Like this:
(define empty-list? empty?)
(define (is-sorted? lst)
(cond
((empty-list? lst) true)
((empty-list? (rest lst)) true)
((string>=? (first lst) (second lst)) false)
(else (is-sorted? (rest lst)))))
It works with your test cases:
(is-sorted? (list)) ; true
(is-sorted? (list "A")) ; true
(is-sorted? (list "B" "A")) ; false
(is-sorted? (list "A" "B")) ; true
(is-sorted? (list "A" "C" "B")) ; false
(is-sorted? (list "A" "B" "C")) ; true
I am new in Lisp programming and trying to create sublists from one single list in lisp with pair of odd and even from the list. for example:
I have a list
ListA ("a" "b" "c" "d" "e" "f" "g" "h")
now I want to convert into the following list:
enter code here
ListB ( ("a" "b") ("c" "d") ("e" "f") ("g" "h") )
so always sublist will be generated with the value of ( (first second) (third fourth) (fifth sixth) ............)
I have tried with mutiple ways for example first take out odd item and even item separate and used the function (list (oddlist evenlist)) but not getting above expected values in the above ListB.Could someone please help me in this regard. Your help would be highly appreciated.
This is actually very short with loop:
(loop for (x y) on '(a b c d e f) by #'cddr
collect (list x y))
;=> ((A B) (C D) (E F))
This does give you a NIL in the last pair if you have an odd number of elements, but you didn't mention what should happen in that case:
(loop for (x y) on '(a b c d e f g ) by #'cddr
collect (list x y))
;=> ((A B) (C D) (E F) (G NIL))
You need to make a procedure that does the following:
handle when argument is (). Usually the result is ()
default case you handle one chain of two. eg. (cons (list "a" "b") recursive-call-here)
So the result of '("g" "h") becomes (cons (list "g" "h") ()) and if you add that to recursive-call-here backwards you end up with:
(cons (list "a" "b")
(cons (list "c" "d")
(cons (list "e" "f")
(cons (list "g" "h") ()))))
; ==> (("a" "b") ("c" "d") ("e" "f") ("g" "h"))
If you already have the even elements separated from the odd ones as you seemed to suggest, the next step would be:
(mapcar #'list evenlist oddlist)
Which one comes first, evenlist or oddlist, depends on whether you started counting from 0 or 1.
Or, the whole problem can be tackled with a single loop expression:
(loop for head = '(a b c d e f g h i j k l m n o p) then (cddr head)
until (null head)
if (= (length head) 1) collect head
else collect (subseq head 0 2))
Say I have a list with keywords:
'(("element1" :keyword1 "a" :keyword2 "b")
("element2" :keyword3 "c" :keyword4 "d")
("element3" :keyword2 "e" :keyword4 "f"))
Which functions can I use to find which list elements contain :keyword2 and find its value in each list? I'm trying to do this in Emacs Lisp but I think with the cl package I could possibly adapt a Common Lisp solution? I've tried to use the find function as illustrated here but to no avail (of course, after changing a few syntax elements to adapt the examples to Emacs Lisp).
(require 'cl)
(defvar *data* '(("element1" :keyword1 "a" :keyword2 "b")
("element2" :keyword3 "c" :keyword4 "d")
("element3" :keyword2 "e" :keyword4 "f")))
(find :keyword2 *data* :test #'find)
;;=> ("element1" :keyword1 "a" :keyword2 "b")
(getf (cdr (find :keyword2 *data* :test #'find)) :keyword2)
;;=> "b"
;; Above only finds the first match; to find all matches,
;; use REMOVE* to remove elements that do not contain the keyword:
(remove* :keyword2 *data* :test-not #'find)
;;=> (("element1" :keyword1 "a" :keyword2 "b")
;; ("element3" :keyword2 "e" :keyword4 "f"))
(mapcar (lambda (x) (getf (cdr x) :keyword2))
(remove* :keyword2 *data* :test-not #'find))
;;=> ("b" "e")
In Common Lisp, you would typically extract the values with destructuring-bind in this case, something like
(destructuring-bind (string &key keyword2 &allow-other-keys)
'("element1" :keyword1 "a" :keyword2 "b")
(list string keyword2)) ; or do anything with string and keyword2
should result in
("element1" "b")
In lisp, you would typically use a so-called associative list (or alist for short). It has the following form:
((key1 . value1) (key2 . value2) (key3 . value3))
There are a number of functions designed to work with alists, including assq and assoc, which return the dotted-pair, or nil.
Install dash list manipulation library (the GitHub link contains instructions). It contains multitude of helpful functions to achieve any goal. Suppose, your list above is named data, then you could:
(--find-indices (-elem-indices :keyword2 it) data) ; => (0 2)
(--map (cadr (--drop-while (not (eq :keyword2 it)) it)) data) ; => ("b" nil "e")
(--map-indexed (cons it-index ; => ((0 . "b") (1) (2 . "e"))
(cadr (--drop-while (not (eq :keyword2 it)) it))) data)
I have a function that takes a list and replaces some elements. I have constructed it as a closure so that the free variable cannot be modified outside of the function.
(defun transform (elems)
(lexical-let ( (elems elems) )
(lambda (seq)
(let (e)
(while (setq e (car elems))
(setf (nth e seq) e)
(setq elems (cdr elems)))
seq))))
I call this on a list of lists.
(defun tester (seq-list)
(let ( (elems '(1 3 5)) )
(mapcar (transform elems) seq-list)))
(tester (list (reverse (number-sequence 1 10))
'("a" "b" "c" "d" "e" "f")))
=> ((10 1 8 3 6 5 4 3 2 1) ("a" "b" "c" "d" "e" "f"))
It does not seem to apply the function to the second element of the list provided to tester(). However, if I explicitly apply this function to the individual elements, it works...
(defun tester (seq-list)
(let ( (elems '(1 3 5)) )
(list (funcall (transform elems) (car seq-list))
(funcall (transform elems) (cadr seq-list)))))
(tester (list (reverse (number-sequence 1 10))
'("a" "b" "c" "d" "e" "f")))
=> ((10 1 8 3 6 5 4 3 2 1) ("a" 1 "c" 3 "e" 5))
If I write a simple function using the same concepts as above, mapcar seems to work... What could I be doing wrong?
(defun transform (x)
(lexical-let ( (x x) )
(lambda (y)
(+ x y))))
(defun tester (seq)
(let ( (x 1) )
(mapcar (transform x) seq)))
(tester (list 1 3))
=> (2 4)
Thanks
The closed-over variable elems is set to nil after the first invocation of the closure; so all subsequent calls only see nil. Your second example works because each instance of transform produces a new closure.
This should work:
(defun transform (elems)
(lexical-let ((elems elems))
(lambda (seq)
(dolist (e elems seq)
(setf (nth e seq) e)))))