From 8e60ef000aa39a6e19d92dda6ae34a8038a538b8 Mon Sep 17 00:00:00 2001 From: Majid Sajadi Date: Sun, 12 Sep 2021 18:25:52 +0430 Subject: [PATCH 1/5] feat(collections): add joinToString --- collections/README.md | 26 +++++++++ collections/join_to_string.ts | 59 +++++++++++++++++++ collections/join_to_string_test.ts | 93 ++++++++++++++++++++++++++++++ collections/mod.ts | 1 + 4 files changed, 179 insertions(+) create mode 100644 collections/join_to_string.ts create mode 100644 collections/join_to_string_test.ts diff --git a/collections/README.md b/collections/README.md index 74e78b655ead..2d85e7c16f81 100644 --- a/collections/README.md +++ b/collections/README.md @@ -455,3 +455,29 @@ console.assert( ], ); ``` + +### joinToString + +Transforms the elements in the given array to strings using the given selector. +Joins the produced strings into one using the given separator and applying the +given prefix and suffix to the whole string afterwards. Returns the resulting +string + +```ts +import { joinToString } from "https://deno.land/std@$STD_VERSION/collections/mod.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; + +const users = [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, +]; + +const names = joinToString(users, (it) => it.name, { + separator: " and ", + prefix: "<", + suffix: ">", +}); + +assertEquals(names, ""); +``` diff --git a/collections/join_to_string.ts b/collections/join_to_string.ts new file mode 100644 index 000000000000..f82c6444c2ac --- /dev/null +++ b/collections/join_to_string.ts @@ -0,0 +1,59 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +/** + * JoinToString + */ +export type JoinToStringOptions = { + separator?: string; + prefix?: string; + suffix?: string; +}; + +/** + * Transforms the elements in the given array to strings using the given selector. Joins the produced strings into one using the given separator and applying the given prefix and suffix to the whole string afterwards. Returns the resulting string. + * + * Example: + * + * ```ts + * import { joinToString } from "./join_to_string.ts"; + * import { assertEquals } from "../testing/asserts.ts"; + * + * const users = [ + * { name: 'Kim', age: 22 }, + * { name: 'Anna', age: 31 }, + * { name: 'Tim', age: 58 }, + * ]; + * + * const names = joinToString(users, + * (it) => it.name, + * { + * separator = " and ", + * prefix = "<", + * suffix = ">", + * } + * ) + * + * assertEquals(names, "") + * ``` + */ +export function joinToString( + array: readonly T[], + selector: (el: T) => string, + { + separator = ", ", + prefix = "", + suffix = "", + }: Readonly = {}, +): string { + let ret = prefix; + + array.forEach((it, index) => { + if (index > 0) { + ret += separator; + } + + ret += selector(it); + }); + + return (ret += suffix); +} diff --git a/collections/join_to_string_test.ts b/collections/join_to_string_test.ts new file mode 100644 index 000000000000..d56193e5ddff --- /dev/null +++ b/collections/join_to_string_test.ts @@ -0,0 +1,93 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +import { assertEquals } from "../testing/asserts.ts"; +import { joinToString, JoinToStringOptions } from "./join_to_string.ts"; + +Deno.test({ + name: "[collections/joinToString] no mutation", + fn() { + const array = [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, + ]; + joinToString(array, (it) => it.name); + + assertEquals(array, [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, + ]); + }, +}); + +Deno.test({ + name: "[collections/joinToString] identity", + fn() { + const array = ["Kim", "Anna", "Tim"]; + + const out = joinToString(array, (it) => it); + + assertEquals(out, "Kim, Anna, Tim"); + }, +}); + +Deno.test({ + name: "[collections/joinToString] normal mapppers", + fn() { + const array = [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, + ]; + const out = joinToString(array, (it) => it.name); + + assertEquals(out, "Kim, Anna, Tim"); + }, +}); + +Deno.test({ + name: "[collections/joinToString] separator", + fn() { + const array = [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, + ]; + const out = joinToString(array, (it) => it.name, { separator: " and " }); + + assertEquals(out, "Kim and Anna and Tim"); + }, +}); + +Deno.test({ + name: "[collections/joinToString] prefix", + fn() { + const array = [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, + ]; + const out = joinToString(array, (it) => it.name, { + prefix: "winners are: ", + }); + + assertEquals(out, "winners are: Kim, Anna, Tim"); + }, +}); + +Deno.test({ + name: "[collections/joinToString] suffix", + fn() { + const array = [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, + ]; + const out = joinToString(array, (it) => it.name, { + suffix: " are winners", + }); + + assertEquals(out, "Kim, Anna, Tim are winners"); + }, +}); diff --git a/collections/mod.ts b/collections/mod.ts index a5c2f126371c..abf3a1779fde 100644 --- a/collections/mod.ts +++ b/collections/mod.ts @@ -23,3 +23,4 @@ export * from "./sort_by.ts"; export * from "./union.ts"; export * from "./unzip.ts"; export * from "./zip.ts"; +export * from "./join_to_string.ts"; From 18f146a8f2d4e30e340390f7caee2a0b0c678928 Mon Sep 17 00:00:00 2001 From: Majid Sajadi Date: Sun, 12 Sep 2021 23:05:05 +0430 Subject: [PATCH 2/5] ref(collections): fix lint errors --- collections/README.md | 10 +++++----- collections/join_to_string.ts | 30 +++++++++++++++++------------- collections/join_to_string_test.ts | 20 +++++++++++++++++++- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/collections/README.md b/collections/README.md index 2d85e7c16f81..620d82387e5a 100644 --- a/collections/README.md +++ b/collections/README.md @@ -468,16 +468,16 @@ import { joinToString } from "https://deno.land/std@$STD_VERSION/collections/mod import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; const users = [ - { name: "Kim", age: 22 }, - { name: "Anna", age: 31 }, - { name: "Tim", age: 58 }, + { name: "Kim" }, + { name: "Anna" }, + { name: "Tim" }, ]; -const names = joinToString(users, (it) => it.name, { +const message = joinToString(users, (it) => it.name, { separator: " and ", prefix: "<", suffix: ">", }); -assertEquals(names, ""); +assertEquals(message, ""); ``` diff --git a/collections/join_to_string.ts b/collections/join_to_string.ts index f82c6444c2ac..a9ddb0020468 100644 --- a/collections/join_to_string.ts +++ b/collections/join_to_string.ts @@ -1,7 +1,7 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. /** - * JoinToString + * Options for joinToString */ export type JoinToStringOptions = { separator?: string; @@ -10,7 +10,9 @@ export type JoinToStringOptions = { }; /** - * Transforms the elements in the given array to strings using the given selector. Joins the produced strings into one using the given separator and applying the given prefix and suffix to the whole string afterwards. Returns the resulting string. + * Transforms the elements in the given array to strings using the given selector. + * Joins the produced strings into one using the given separator and applying the given prefix and suffix to the whole string afterwards. + * Returns the resulting string. * * Example: * @@ -19,21 +21,21 @@ export type JoinToStringOptions = { * import { assertEquals } from "../testing/asserts.ts"; * * const users = [ - * { name: 'Kim', age: 22 }, - * { name: 'Anna', age: 31 }, - * { name: 'Tim', age: 58 }, + * { name: 'Kim' }, + * { name: 'Anna' }, + * { name: 'Tim' }, * ]; * - * const names = joinToString(users, + * const message = joinToString(users, * (it) => it.name, * { - * separator = " and ", - * prefix = "<", - * suffix = ">", - * } - * ) + * separator: " and ", + * prefix: "<", + * suffix: ">", + * }, + * ); * - * assertEquals(names, "") + * assertEquals(message, ""); * ``` */ export function joinToString( @@ -55,5 +57,7 @@ export function joinToString( ret += selector(it); }); - return (ret += suffix); + ret += suffix; + + return ret; } diff --git a/collections/join_to_string_test.ts b/collections/join_to_string_test.ts index d56193e5ddff..6f432b17165e 100644 --- a/collections/join_to_string_test.ts +++ b/collections/join_to_string_test.ts @@ -1,7 +1,7 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. import { assertEquals } from "../testing/asserts.ts"; -import { joinToString, JoinToStringOptions } from "./join_to_string.ts"; +import { joinToString } from "./join_to_string.ts"; Deno.test({ name: "[collections/joinToString] no mutation", @@ -91,3 +91,21 @@ Deno.test({ assertEquals(out, "Kim, Anna, Tim are winners"); }, }); + +Deno.test({ + name: "[collections/joinToString] all options", + fn() { + const array = [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, + ]; + const out = joinToString(array, (it) => it.name, { + suffix: " are winners", + prefix: "result ", + separator: " and ", + }); + + assertEquals(out, "Kim, Anna, Tim are winners"); + }, +}); From 1c09899550f013b537f798f339d374eab1409cbe Mon Sep 17 00:00:00 2001 From: Majid Sajadi Date: Fri, 17 Sep 2021 20:20:37 +0430 Subject: [PATCH 3/5] add truncate --- collections/join_to_string.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/collections/join_to_string.ts b/collections/join_to_string.ts index a9ddb0020468..04846c49bcce 100644 --- a/collections/join_to_string.ts +++ b/collections/join_to_string.ts @@ -7,6 +7,10 @@ export type JoinToStringOptions = { separator?: string; prefix?: string; suffix?: string; + truncate?: { + after: number; + with?: string; + }; }; /** @@ -42,9 +46,13 @@ export function joinToString( array: readonly T[], selector: (el: T) => string, { - separator = ", ", + separator = ",", prefix = "", suffix = "", + truncate = { + after: -1, + with: "...", + }, }: Readonly = {}, ): string { let ret = prefix; @@ -55,6 +63,11 @@ export function joinToString( } ret += selector(it); + + if (truncate.after > -1 && index === truncate.after) { + ret += truncate.with; + break; + } }); ret += suffix; From 2d8b39abd2df97f1eb98c65cff11aa0e79afe541 Mon Sep 17 00:00:00 2001 From: Majid Sajadi Date: Sat, 9 Oct 2021 17:06:36 +0330 Subject: [PATCH 4/5] ref: add truncated to joinToString --- collections/README.md | 3 +- collections/join_to_string.ts | 65 +++++++++++++------------ collections/join_to_string_test.ts | 77 ++++++++++++++++++++++-------- 3 files changed, 89 insertions(+), 56 deletions(-) diff --git a/collections/README.md b/collections/README.md index 6acff307b973..9f71cafe3ae9 100644 --- a/collections/README.md +++ b/collections/README.md @@ -654,7 +654,7 @@ const users = [ { name: "Tim" }, ]; -const message = joinToString(array, (it) => it.name, { +const message = joinToString(users, (it) => it.name, { suffix: " are winners", prefix: "result: ", separator: " and ", @@ -882,5 +882,4 @@ const numbers = [1, 2, 3, 4, 5]; const sumSteps = runningReduce(numbers, (sum, current) => sum + current, 0); assertEquals(sumSteps, [1, 3, 6, 10, 15]); ->>>>>>> 36a270813b581d54ebde4162327ebd98672fbaf7 ``` diff --git a/collections/join_to_string.ts b/collections/join_to_string.ts index 04846c49bcce..41956325f5a2 100644 --- a/collections/join_to_string.ts +++ b/collections/join_to_string.ts @@ -7,39 +7,37 @@ export type JoinToStringOptions = { separator?: string; prefix?: string; suffix?: string; - truncate?: { - after: number; - with?: string; - }; + limit?: number; + truncated?: string; }; /** * Transforms the elements in the given array to strings using the given selector. - * Joins the produced strings into one using the given separator and applying the given prefix and suffix to the whole string afterwards. + * Joins the produced strings into one using the given `separator` and applying the given `prefix` and `suffix` to the whole string afterwards. + * If the array could be huge, you can specify a non-negative value of `limit`, in which case only the first `limit` elements will be appended, followed by the `truncated` string. * Returns the resulting string. * * Example: * * ```ts - * import { joinToString } from "./join_to_string.ts"; - * import { assertEquals } from "../testing/asserts.ts"; + * import { joinToString } from "https://deno.land/std@$STD_VERSION/collections/mod.ts"; + * import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; * * const users = [ - * { name: 'Kim' }, - * { name: 'Anna' }, - * { name: 'Tim' }, + * { name: "Kim" }, + * { name: "Anna" }, + * { name: "Tim" }, * ]; * - * const message = joinToString(users, - * (it) => it.name, - * { - * separator: " and ", - * prefix: "<", - * suffix: ">", - * }, - * ); + * const message = joinToString(users, (it) => it.name, { + * suffix: " are winners", + * prefix: "result: ", + * separator: " and ", + * limit: 1, + * truncated: "others", + * }); * - * assertEquals(message, ""); + * assertEquals(message, "result: Kim and others are winners"); * ``` */ export function joinToString( @@ -49,28 +47,29 @@ export function joinToString( separator = ",", prefix = "", suffix = "", - truncate = { - after: -1, - with: "...", - }, + limit = -1, + truncated = "...", }: Readonly = {}, ): string { - let ret = prefix; + let result = ""; + + let index = -1; + while (++index < array.length) { + const el = array[index]; - array.forEach((it, index) => { if (index > 0) { - ret += separator; + result += separator; } - ret += selector(it); - - if (truncate.after > -1 && index === truncate.after) { - ret += truncate.with; + if (limit > -1 && index >= limit) { + result += truncated; break; } - }); - ret += suffix; + result += selector(el); + } + + result = prefix + result + suffix; - return ret; + return result; } diff --git a/collections/join_to_string_test.ts b/collections/join_to_string_test.ts index 6f432b17165e..70edb9df87a7 100644 --- a/collections/join_to_string_test.ts +++ b/collections/join_to_string_test.ts @@ -6,14 +6,14 @@ import { joinToString } from "./join_to_string.ts"; Deno.test({ name: "[collections/joinToString] no mutation", fn() { - const array = [ + const arr = [ { name: "Kim", age: 22 }, { name: "Anna", age: 31 }, { name: "Tim", age: 58 }, ]; - joinToString(array, (it) => it.name); + joinToString(arr, (it) => it.name); - assertEquals(array, [ + assertEquals(arr, [ { name: "Kim", age: 22 }, { name: "Anna", age: 31 }, { name: "Tim", age: 58 }, @@ -24,37 +24,37 @@ Deno.test({ Deno.test({ name: "[collections/joinToString] identity", fn() { - const array = ["Kim", "Anna", "Tim"]; + const arr = ["Kim", "Anna", "Tim"]; - const out = joinToString(array, (it) => it); + const out = joinToString(arr, (it) => it); - assertEquals(out, "Kim, Anna, Tim"); + assertEquals(out, "Kim,Anna,Tim"); }, }); Deno.test({ name: "[collections/joinToString] normal mapppers", fn() { - const array = [ + const arr = [ { name: "Kim", age: 22 }, { name: "Anna", age: 31 }, { name: "Tim", age: 58 }, ]; - const out = joinToString(array, (it) => it.name); + const out = joinToString(arr, (it) => it.name); - assertEquals(out, "Kim, Anna, Tim"); + assertEquals(out, "Kim,Anna,Tim"); }, }); Deno.test({ name: "[collections/joinToString] separator", fn() { - const array = [ + const arr = [ { name: "Kim", age: 22 }, { name: "Anna", age: 31 }, { name: "Tim", age: 58 }, ]; - const out = joinToString(array, (it) => it.name, { separator: " and " }); + const out = joinToString(arr, (it) => it.name, { separator: " and " }); assertEquals(out, "Kim and Anna and Tim"); }, @@ -63,49 +63,84 @@ Deno.test({ Deno.test({ name: "[collections/joinToString] prefix", fn() { - const array = [ + const arr = [ { name: "Kim", age: 22 }, { name: "Anna", age: 31 }, { name: "Tim", age: 58 }, ]; - const out = joinToString(array, (it) => it.name, { + const out = joinToString(arr, (it) => it.name, { prefix: "winners are: ", }); - assertEquals(out, "winners are: Kim, Anna, Tim"); + assertEquals(out, "winners are: Kim,Anna,Tim"); }, }); Deno.test({ name: "[collections/joinToString] suffix", fn() { - const array = [ + const arr = [ { name: "Kim", age: 22 }, { name: "Anna", age: 31 }, { name: "Tim", age: 58 }, ]; - const out = joinToString(array, (it) => it.name, { + const out = joinToString(arr, (it) => it.name, { suffix: " are winners", }); - assertEquals(out, "Kim, Anna, Tim are winners"); + assertEquals(out, "Kim,Anna,Tim are winners"); + }, +}); + +Deno.test({ + name: "[collections/joinToString] limit", + fn() { + const arr = [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, + ]; + const out = joinToString(arr, (it) => it.name, { + limit: 2, + }); + + assertEquals(out, "Kim,Anna,..."); + }, +}); + +Deno.test({ + name: "[collections/joinToString] truncated", + fn() { + const arr = [ + { name: "Kim", age: 22 }, + { name: "Anna", age: 31 }, + { name: "Tim", age: 58 }, + ]; + const out = joinToString(arr, (it) => it.name, { + limit: 2, + truncated: "...!", + }); + + assertEquals(out, "Kim,Anna,...!"); }, }); Deno.test({ name: "[collections/joinToString] all options", fn() { - const array = [ + const arr = [ { name: "Kim", age: 22 }, { name: "Anna", age: 31 }, { name: "Tim", age: 58 }, ]; - const out = joinToString(array, (it) => it.name, { + const out = joinToString(arr, (it) => it.name, { suffix: " are winners", - prefix: "result ", + prefix: "result: ", separator: " and ", + limit: 1, + truncated: "others", }); - assertEquals(out, "Kim, Anna, Tim are winners"); + assertEquals(out, "result: Kim and others are winners"); }, }); From aef8e422af86120fb17de6027002151691478992 Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Sat, 16 Oct 2021 13:58:18 +0900 Subject: [PATCH 5/5] chore: fmt --- collections/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collections/README.md b/collections/README.md index 2f541c0f134e..3beef70ce330 100644 --- a/collections/README.md +++ b/collections/README.md @@ -880,4 +880,4 @@ assertEquals( [4, "d"], ], ); -``` \ No newline at end of file +```