Tom
Tom

Reputation: 33

how to find whether a vector has consecutive elements in clojure

I am new to clojure I am trying to find whether a vector in clojure has consecutive elements: in python its simple using numpy

(np.diff(np.sort(np.array(numbers))))

But I am lost trying to find similar methods: My strategy was to

  1. subtract a vector with itself
  2. make it a set and see if it contains first element as 1 and the length of set is 1

for example (def x `(5 7 3 6 4)) Output would be (1 1 1 1)

I am confused how to work on this.

Upvotes: 0

Views: 629

Answers (4)

Alex Miller
Alex Miller

Reputation: 70239

Clojure has a built-in dedupe function so an easy (but not particularly fast) answer is to dedupe and compare equals.

(defn consecutive?
  [coll]
  (not= coll (dedupe coll)))

(consecutive? [1 2 2 3])  ;; true
(consecutive? [1 2 3])    ;; false

Upvotes: 1

mikera
mikera

Reputation: 106401

Try something like this:

(defn diff [vals]
   (map - (next vals) vals))

This returns a list of differences between each pair of consecutive elements are equal. It works because next simply offsets the sequence of values by one element.

Example usage:

(diff [1 2 2 3])
=> (1 0 1)

To test whether consecutive numbers exist, you simply need to check for the presence of the value 1 in this list.

Upvotes: 5

Alan Thompson
Alan Thompson

Reputation: 29984

Please see this list of documentation, especially the Clojure CheatSheet. You are looking for the function partition. You can use it like this:

(ns tst.demo.core
  (:use tupelo.test))

(defn pair-delta
  [pair]
  (let [[a b] pair]
    (- b a)))

(defn consectives?
  [v]
  (let [pairs  (partition 2 1 (sort v))
        deltas (mapv pair-delta pairs)
        result (= #{1} (set deltas))]
    result))

(dotest
  (let [pos  [1 2 3 6 5 4]
        neg  [1 2 3 6 5  ]]
    (is= true (consectives? pos))
    (is= false (consectives? neg))))

The template project shows how I like to set up a project, and includes my favorite helper functions.

Upvotes: -1

jas
jas

Reputation: 10865

Following your idea of getting the differences, after sorting you can use partition to get all the consecutive pairs and than use map to get all the differences. (Here it seemed more natural to get the reverse of the numpy diff, so the check is that every element is -1 instead of 1.)

(defn contains-consecutive? [xs]
  (let [sorted (sort xs)
        differences (map #(apply - %) (partition 2 1 sorted))]
    (every? #(= -1 %) differences)))


user> (contains-consecutive? [])
true
user> (contains-consecutive? [1])
true
user> (contains-consecutive? [1 3 2])
true
user> (contains-consecutive? [1 3 4])
false
user> (contains-consecutive? '(5 7 3 6 4))
true

Upvotes: 1

Related Questions