Clojure:列表中的复杂迭代? [英] Clojure: Complex Iteration Across a List?

查看:126
本文介绍了Clojure:列表中的复杂迭代?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个数字,20和一个列表。 '(1 2 3 4 5 6 7 8 9 10),并返回一个包含原始列表中每个值两个值的集合:原始值与余数配对潜水20的值。如果原始值以某种方式被键入余数,那么这将是很好的,所以我可以很容易地检索每个数字,产生一个特定的余数。基本上我想要一些函数 func

  user => (func 20'(1 2 3 4 5 6 7 8 9 10))
'(:0 1,:0 2,:2 3,...:20 0)

然而,我有一个令人难以置信的困难时间,只是弄清楚如何迭代通过列表。有人可以帮助我理解如何独立使用列表的元素,然后如何返回20被除以和如果它返回一个余数的元素?



我的思想是在计算平方根的程序中使用类似这样的东西。如果数字由余数键入,那么我可以查询集合以获得所有将余数为0的数字。






这是我的初步方式。

  ;;我最好的方法找到一个平方根的想法很简单。 
;;如果我想找到n的平方根,将n分成两半
;;然后将我们的初始数字(n)除以范围内的所有数字0 ... n / 2
;;分离出一个只返回余数为0的结果列表。
;;然后测试结果的比较,看看我们返回的元素是否
;;列表当平方等于我们想找到的平方根的数字。
;;首先我将开发一个与evens和赔率一起使用的函数

(defn sqroot-range-high-end [input](/ input 2))
(sqroot-range-high结束36); 18

(defn make-sqrt-range [input](range(sqroot-range-high-end(+ 1 input))))
(make-sqrt- range 36); '(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)

(defn zero-culler [input](lazy-seq(remove zero? -range input))))
(zero-culler 100); '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)

(defn odd-culler [input](lazy-seq(remove odd? ))))
(odd-culler 100); '(2 4 6 8 10 12 14 16 18)

;;下面是我被卡住的地方
;;我是clojure和编程的新手,
;;并且只是试图以一种我理解的方式学习

(defn remainder -culler [input]
(如果
(/ input(first odd-culler(input)) )
输入)
(recur(lazy-seq(input)))


(remaining-culler 100)


解决方案

欢迎使用Clojure!



快速备注: [1 2 3 4 5 6 7 8 9 10] 是向量,不是列表。



p>

这里是 Clojure的骗子,非常方便。您正在尝试从函数创建地图。地图是一种集合,因此,如果您转到集合部分的骗子,并向下滚动到地图,您会看到一些类别。您想要创建一个,所以请查看该列表,并浏览到Clojure的文档链接。



这将导致非常方便的 group-by 功能。你给它一个函数和一个集合,并返回一个包含该集合中的所有项目的映射,由将f应用于每个值的结果决定。

 > (group-by#(rem 20%)[1 2 3 4 5 6 7 8 9 10])
{0 [1 2 4 5 10],2 [3 6 9],6 [7],4 [8]}

如果你想让键是实际的关键字,匿名函数返回关键字:

 > (group-by#(keyword(str(rem 20%)))
{:0 [1 2 4 5 10],:2 [3 6 9 ],:6 [7],:4 [8]}

载体。这是因为您无法从单个键映射到两个项目(即,映射编码函数)。



迭代/列表理解 / p>

现在,所有的说,我不知道这是你要找的。你问,有人可以帮助我理解如何独立使用列表的元素,然后如何返回20被除以的元素,如果它返回一个余数?这听起来像是 for 。为了您的目的,您可以将其视为迭代,但它确实是列表 理解

 (for [i [1 2 3 4 5 6 7 8 9 10]] 
(list(rem 20 i)i))
 (for [i [1 2 3 4 5 6 7 8 9 10]] 
(list(keyword(str(rem 20 i)))i))



在这个特殊情况下,正如Kyle指出的,你可以使用map:

 (map#(list(keyword(str(rem 20%)))
%)
[1 2 3 4 5 6 7 8 9 10])

如果您不喜欢这些返回的嵌套结构,可以使用 flatten



过滤



但我还是不确定你想要这个来解决你的问题。在你的注释中,你有分离出只返回余数为0的结果列表。这听起来像是 过滤器 ,作为副作用是懒惰。

 > (过滤器#(零→(rem 20%))
(1 2 4 5 10)

Ta-da。它只是吐出了符合你的需求的原始集合的元素。



希望这有助于。它不会让你一路走向你的目标,但我希望它给你一些整洁的工具,你可以用来到那里。你有选择!当你学习时,玩弄多种选择。如果你读某个地方比另一个更好,看看你能找出为什么。


I'd like to take a number, 20, and a list. '(1 2 3 4 5 6 7 8 9 10), and return a collection containing two values for each value in the original list: the original value paired with the remainder when diving 20 by that value. It would be nice if the original values were somehow keyed to the remainders, so that I could easily retrieve each number that produced a particular remainder. Basically I want some function func:

user=> (func 20 '(1 2 3 4 5 6 7 8 9 10))
'(:0 1, :0 2, :2 3,... :20 0)

I am however having an incredibly difficult time just figuring out how to iterate through the list. Could someone help me understand how to use the elements of a list independently, and then how to return the element that 20 was divided by and if it returns a remainder?

My thought was to use something like this in a program that calculates square roots. If the numbers were keyed by the remainder, then I could query the collection to get all numbers that divide the input with a remainder of 0.


Here was my preliminary way of going about that.

;; My idea on the best way to find a square root is simple.
;; If I want to find the square root of n, divide n in half
;; Then divide our initial number (n) by all numbers in the range 0...n/2 
;; Separate out a list of results that only only return a remainder of 0.
;; Then test the results in a comparison to see if the elements of our returned 
;; list when squared are equal with the number we want to find a square root of.
;; First I'll develop a function that works with evens and then odds

(defn sqroot-range-high-end [input] (/ input 2))
(sqroot-range-high-end 36) ; 18

(defn make-sqrt-range [input] (range (sqroot-range-high-end (+ 1 input))))
(make-sqrt-range 36) ; '(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)

(defn zero-culler [input] (lazy-seq (remove zero? (make-sqrt-range input))))
(zero-culler 100) ; '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)

(defn odd-culler [input] (lazy-seq (remove odd? (zero-culler input))))
(odd-culler 100) ; '(2 4 6 8 10 12 14 16 18)

;;the following is where I got stuck
;;I'm new to clojure and programming,
;;and am just trying to learn in a way that I understand

(defn remainder-culler [input]
  (if
    (/ input (first odd-culler (input)))
  input)
  (recur (lazy-seq (input)))
)

(remainder-culler 100)

解决方案

Welcome to Clojure!

A quick note: [1 2 3 4 5 6 7 8 9 10] is a vector, not a list.

When you say "keyed to," then it makes me think you're looking for something that returns a map.

Maps

This is where Clojure's cheatsheet comes in really handy. You're trying to create a map from a function. A map is a kind of collection, so if you go to the "Collections" section on the cheatsheet, and scroll down to maps, you will see a number of categories. You want to create one, so look in that list, and explore the links to Clojure's documentation.

This leads you to the very handy group-by function. You give it a function, and a collection, and it returns a map containing all of the items from that collection, keyed by the result of applying f to each value.

> (group-by #(rem 20 %) [1 2 3 4 5 6 7 8 9 10])
{0 [1 2 4 5 10], 2 [3 6 9], 6 [7], 4 [8]}

If you want to make the keys be actual keywords, you'll have to modify the anonymous function to give back keywords:

> (group-by #(keyword (str (rem 20 %))) [1 2 3 4 5 6 7 8 9 10])
{:0 [1 2 4 5 10], :2 [3 6 9], :6 [7], :4 [8]}

Note that the return values are in vectors. This is because you can't map to two items from a single key (i.e., maps encode functions).

Iteration/List Comprehension

Now, all of that said, I'm not sure it's what you're looking for. You asked, "Could someone help me understand how to use the elements of a list independently, and then how to return the element that 20 was divided by and if it returns a remainder?" This sounds to me like a case for for. For your purposes, you can think of it as iterating, but it's really doing list comprehension.

(for [i [1 2 3 4 5 6 7 8 9 10]]
    (list (rem 20 i) i))

Once again, if you actually want to use keywords instead of values, then you could do:

(for [i [1 2 3 4 5 6 7 8 9 10]]
    (list (keyword (str (rem 20 i))) i))

In this particular case, as Kyle points out, you might just use map:

(map #(list (keyword (str (rem 20 %)))
            %)
     [1 2 3 4 5 6 7 8 9 10])

If you don't like the nested structures that these return, you can use flatten on them.

Filter

But I'm still not sure you want this to solve your problem. In your comments, you have "Separate out a list of results that only only return a remainder of 0." This sounds to me like a case for filter, which as a side-benefit is lazy.

> (filter #(zero? (rem 20 %)) [1 2 3 4 5 6 7 8 9 10])
(1 2 4 5 10)

Ta-da. It just spits out the elements of the original collection that meet your needs.

Hope this helps. It doesn't get you all the way toward your goal, but I hope it gives you some neat tools you might use to get there. You have options! And while you're learning, play around with multiple options. If you read somewhere that one is preferable to another, see if you can figure out why.

这篇关于Clojure:列表中的复杂迭代?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆