From 6aaaec43f8ec8696129ce7b70f70eaf174202f93 Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Tue, 18 Feb 2020 09:19:24 -0500 Subject: [PATCH 1/4] Add `sequtils.unzip` to complement `sequtils.zip` --- changelog.md | 2 +- lib/pure/collections/sequtils.nim | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index ad18bec6b7610..ce47249a8259e 100644 --- a/changelog.md +++ b/changelog.md @@ -61,7 +61,7 @@ - Added `wrapnils` module for chains of field-access and indexing where the LHS can be nil. This simplifies code by reducing need for if-else branches around intermediate maybe nil values. E.g. `echo ?.n.typ.kind` -- Added `minIndex` and `maxIndex` to the `sequtils` module +- Added `minIndex`, `maxIndex` and `unzip` to the `sequtils` module. - Added `os.isRelativeTo` to tell whether a path is relative to another - Added `resetOutputFormatters` to `unittest` diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index d56742ba9012c..c654fcf67ada9 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -281,6 +281,19 @@ when (NimMajor, NimMinor) <= (1, 0): else: zipImpl(s1, s2, seq[(S, T)]) +proc unzip*[S, T](s: openArray[(S, T)]): (seq[S], seq[T]) = + ## Returns a tuple of two sequences split out from a sequence of 2-field tuples. + runnableExamples: + let + zipped = @[(1, 'a'), (2, 'b'), (3, 'c')] + unzipped1 = @[1, 2, 3] + unzipped2 = @['a', 'b', 'c'] + assert zipped.unzip() == (unzipped1, unzipped2) + assert zip(unzipped1, unzipped2).unzip() == (unzipped1, unzipped2) + for elem in s: + result[0].add(elem[0]) + result[1].add(elem[1]) + proc distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] = ## Splits and distributes a sequence `s` into `num` sub-sequences. ## From 1aaeda406e953d46033b6cc28232b5c50fa28a47 Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Tue, 18 Feb 2020 09:25:56 -0500 Subject: [PATCH 2/4] sequtils.unzip: Init the `result` sequences Co-Authored-By: Vindaar --- lib/pure/collections/sequtils.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index c654fcf67ada9..631fa1b0f86a3 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -290,6 +290,8 @@ proc unzip*[S, T](s: openArray[(S, T)]): (seq[S], seq[T]) = unzipped2 = @['a', 'b', 'c'] assert zipped.unzip() == (unzipped1, unzipped2) assert zip(unzipped1, unzipped2).unzip() == (unzipped1, unzipped2) + result[0] = newSeqOfCap[S](s.len) + result[1] = newSeqOfCap[T](s.len) for elem in s: result[0].add(elem[0]) result[1].add(elem[1]) From c454ec6b08ed0f5ba852b15d4d4e5dcbc703f211 Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Tue, 18 Feb 2020 09:32:11 -0500 Subject: [PATCH 3/4] sequtils.unzip: Allocate the result seqs just once Thanks to @def- for the suggestion. --- lib/pure/collections/sequtils.nim | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 631fa1b0f86a3..469144ab542f6 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -290,11 +290,11 @@ proc unzip*[S, T](s: openArray[(S, T)]): (seq[S], seq[T]) = unzipped2 = @['a', 'b', 'c'] assert zipped.unzip() == (unzipped1, unzipped2) assert zip(unzipped1, unzipped2).unzip() == (unzipped1, unzipped2) - result[0] = newSeqOfCap[S](s.len) - result[1] = newSeqOfCap[T](s.len) - for elem in s: - result[0].add(elem[0]) - result[1].add(elem[1]) + result[0] = newSeq[S](s.len) + result[1] = newSeq[T](s.len) + for i in 0 ..< s.len: + result[0][i] = s[i][0] + result[1][i] = s[i][1] proc distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] = ## Splits and distributes a sequence `s` into `num` sub-sequences. From d98f4af7798969d3370d89206c98a1e9acff5130 Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Wed, 19 Feb 2020 08:34:11 -0500 Subject: [PATCH 4/4] sequtils.unzip: Revert back to using newSeqOfCap; add since pragma --- lib/pure/collections/sequtils.nim | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 469144ab542f6..ac220137754a6 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -281,7 +281,7 @@ when (NimMajor, NimMinor) <= (1, 0): else: zipImpl(s1, s2, seq[(S, T)]) -proc unzip*[S, T](s: openArray[(S, T)]): (seq[S], seq[T]) = +proc unzip*[S, T](s: openArray[(S, T)]): (seq[S], seq[T]) {.since: (1, 1).} = ## Returns a tuple of two sequences split out from a sequence of 2-field tuples. runnableExamples: let @@ -290,11 +290,11 @@ proc unzip*[S, T](s: openArray[(S, T)]): (seq[S], seq[T]) = unzipped2 = @['a', 'b', 'c'] assert zipped.unzip() == (unzipped1, unzipped2) assert zip(unzipped1, unzipped2).unzip() == (unzipped1, unzipped2) - result[0] = newSeq[S](s.len) - result[1] = newSeq[T](s.len) - for i in 0 ..< s.len: - result[0][i] = s[i][0] - result[1][i] = s[i][1] + result[0] = newSeqOfCap[S](s.len) + result[1] = newSeqOfCap[T](s.len) + for elem in s: + result[0].add(elem[0]) + result[1].add(elem[1]) proc distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] = ## Splits and distributes a sequence `s` into `num` sub-sequences.