-
Notifications
You must be signed in to change notification settings - Fork 0
Extract common utility functions #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
395a6eb
2e1cc11
d7886e9
5a3d0d4
512d777
f94f7ab
e5f22df
cffbcd7
02760fd
2300673
83fe1f5
d21606f
bf6bb95
bca8364
6d903ab
446452d
c3aef80
a67a111
c31632d
f3dc2a2
4bf3101
477c240
62dfd9f
dd46940
b39b5c4
19c987c
83f23da
b40fc5c
175ae7b
288bafd
036d35b
e8c6b69
1f919ff
476327a
329dab5
e995e9f
4b83314
bd6b135
ea8a3ba
c3470ec
ba709d0
8e883fb
de232d9
0e569d0
4881f5f
8911d90
990589d
13ffd95
d798b98
b299bb8
56357f5
c056f7e
89488a4
f31a2e0
1088a05
19aac26
011e83a
e101e40
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "files": [ | ||
| "README.md" | ||
| ], | ||
| "imageSize": 100, | ||
| "commit": false, | ||
| "contributors": [ | ||
| { | ||
| "login": "sandstreamdevelopment", | ||
| "name": "sandstreamdevelopment", | ||
| "avatar_url": "https://avatars2.githubusercontent.com/u/44231396?v=4", | ||
| "profile": "https://github.com/sandstreamdevelopment", | ||
| "contributions": [ | ||
| "business", | ||
| "financial", | ||
| "ideas" | ||
| ] | ||
| } | ||
| ], | ||
| "contributorsPerLine": 7, | ||
| "projectName": "std", | ||
| "projectOwner": "sandstreamdev", | ||
| "repoType": "github", | ||
| "repoHost": "https://github.com" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,3 +59,6 @@ typings/ | |
|
|
||
| # next.js build output | ||
| .next | ||
|
|
||
| index.cjs.js | ||
| index.umd.js | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| regenerate.js |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,19 @@ | ||
| # std | ||
| # std | ||
|
|
||
| [](#contributors) | ||
|
|
||
| ## Contributors ✨ | ||
|
|
||
| Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): | ||
|
|
||
| <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> | ||
| <!-- prettier-ignore --> | ||
| <table> | ||
| <tr> | ||
| <td align="center"><a href="https://github.com/sandstreamdevelopment"><img src="https://avatars2.githubusercontent.com/u/44231396?v=4" width="100px;" alt="sandstreamdevelopment"/><br /><sub><b>sandstreamdevelopment</b></sub></a><br /><a href="#business-sandstreamdevelopment" title="Business development">💼</a> <a href="#financial-sandstreamdevelopment" title="Financial">💵</a> <a href="#ideas-sandstreamdevelopment" title="Ideas, Planning, & Feedback">🤔</a></td> | ||
| </tr> | ||
| </table> | ||
|
|
||
| <!-- ALL-CONTRIBUTORS-LIST:END --> | ||
|
|
||
| This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => xs && xs.length > 0; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import is from "./is.js"; | ||
|
|
||
| export default (...xs) => xs.every(is); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export default (xs, ys) => { | ||
| const zs = new Set(ys); | ||
|
|
||
| return xs.filter(x => !zs.has(x)); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export default (xs, ys) => | ||
| (!xs && ys) || | ||
| (!ys && xs) || | ||
| xs.length !== ys.length || | ||
| xs.some((x, index) => x !== ys[index]); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export default xs => | ||
| xs.filter((value, index, self) => self.indexOf(value) !== index); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please correct me if I'm wrong - what is the intent of this function?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It returns the duplicated values (values that occur more than once). A single law this function must obey is that a set of unique elements and the duplicates of some set is equal to itself: equal(
sort([...unique(xs), ...duplicates(xs)]),
sort(xs)
)By that, the only correct interpretation is the last definition - it returns a list of values that occurs more than once.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, good to know the idea, which you had behind that function - definitely we are missing docs. So.. maybe we should add |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default []; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import range from "./range.js"; | ||
|
|
||
| export default n => xs => range(n).map(index => xs[index]); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default y => xs => xs.filter(x => x !== y); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| export default f => xs => { | ||
| let i = 0; | ||
| let j = 0; | ||
|
|
||
| while (i < xs.length) { | ||
| const value = xs[i]; | ||
| if (f(value, i, xs)) { | ||
| xs[j++] = value; | ||
| } | ||
| i++; | ||
| } | ||
|
|
||
| xs.length = j; | ||
| return xs; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| export default (predicate, fallback) => xs => { | ||
| const target = xs.find(predicate); | ||
| return target !== undefined ? target : fallback; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default ([x]) => x; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default f => xs => xs.reduce((ys, y) => ys.concat(f(y)), []); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => [].concat(...xs); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| import any from "./any.js"; | ||
| import are from "./are.js"; | ||
| import difference from "./difference.js"; | ||
| import differs from "./differs.js"; | ||
| import duplicates from "./duplicates.js"; | ||
| import empty from "./empty.js"; | ||
| import exact from "./exact.js"; | ||
| import except from "./except.js"; | ||
| import filterInPlace from "./filterInPlace.js"; | ||
| import find from "./find.js"; | ||
| import first from "./first.js"; | ||
| import flatMap from "./flatMap.js"; | ||
| import flatten from "./flatten.js"; | ||
| import intersection from "./intersection.js"; | ||
| import is from "./is.js"; | ||
| import last from "./last.js"; | ||
| import lengthDiffers from "./lengthDiffers.js"; | ||
| import map from "./map.js"; | ||
| import midpoint from "./midpoint.js"; | ||
| import minMax from "./minMax.js"; | ||
| import multiple from "./multiple.js"; | ||
| import none from "./none.js"; | ||
| import partition from "./partition.js"; | ||
| import range from "./range.js"; | ||
| import repeat from "./repeat.js"; | ||
| import reverse from "./reverse.js"; | ||
| import reverseIf from "./reverseIf.js"; | ||
| import rotate from "./rotate.js"; | ||
| import second from "./second.js"; | ||
| import secondToLast from "./secondToLast.js"; | ||
| import shift from "./shift.js"; | ||
| import shuffle from "./shuffle.js"; | ||
| import shuffleInPlace from "./shuffleInPlace.js"; | ||
| import single from "./single.js"; | ||
| import sort from "./sort.js"; | ||
| import sum from "./sum.js"; | ||
| import transpose from "./transpose.js"; | ||
| import unique from "./unique.js"; | ||
| import zip from "./zip.js"; | ||
| import zipWith from "./zipWith.js"; | ||
|
|
||
| export { | ||
| any, | ||
| are, | ||
| difference, | ||
| differs, | ||
| duplicates, | ||
| empty, | ||
| exact, | ||
| except, | ||
| filterInPlace, | ||
| find, | ||
| first, | ||
| flatMap, | ||
| flatten, | ||
| intersection, | ||
| is, | ||
| last, | ||
| lengthDiffers, | ||
| map, | ||
| midpoint, | ||
| minMax, | ||
| multiple, | ||
| none, | ||
| partition, | ||
| range, | ||
| repeat, | ||
| reverse, | ||
| reverseIf, | ||
| rotate, | ||
| second, | ||
| secondToLast, | ||
| shift, | ||
| shuffle, | ||
| shuffleInPlace, | ||
| single, | ||
| sort, | ||
| sum, | ||
| transpose, | ||
| unique, | ||
| zip, | ||
| zipWith | ||
| }; | ||
|
|
||
| export default { | ||
| any, | ||
| are, | ||
| difference, | ||
| differs, | ||
| duplicates, | ||
| empty, | ||
| exact, | ||
| except, | ||
| filterInPlace, | ||
| find, | ||
| first, | ||
| flatMap, | ||
| flatten, | ||
| intersection, | ||
| is, | ||
| last, | ||
| lengthDiffers, | ||
| map, | ||
| midpoint, | ||
| minMax, | ||
| multiple, | ||
| none, | ||
| partition, | ||
| range, | ||
| repeat, | ||
| reverse, | ||
| reverseIf, | ||
| rotate, | ||
| second, | ||
| secondToLast, | ||
| shift, | ||
| shuffle, | ||
| shuffleInPlace, | ||
| single, | ||
| sort, | ||
| sum, | ||
| transpose, | ||
| unique, | ||
| zip, | ||
| zipWith | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default (xs, ys) => xs.filter(value => ys.includes(value)); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default value => Array.isArray(value); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => xs[xs.length - 1]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default (a, b) => a.length !== b.length; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| export default (...fs) => { | ||
| const f = x => fs.reduce((x, f) => f(x), x); | ||
| return x => x.map(f); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => xs[Math.floor(xs.length / 2)]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| const { max, min } = Math; | ||
|
|
||
| export default ([head, ...tail]) => | ||
| tail.reduce(([min, max], current) => [min(min, current), max(max, current)], [ | ||
| head, | ||
| head | ||
| ]); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => xs.length > 1; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import any from "./any.js"; | ||
|
|
||
| export default xs => !any(xs); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| export default predicate => xs => | ||
| xs.reduce( | ||
| ([left, right], current) => { | ||
| const pass = predicate(current); | ||
| return pass ? [left, [...right, current]] : [[...left, current], right]; | ||
| }, | ||
| [[], []] | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| export default n => | ||
| Array(n) | ||
| .fill() | ||
| .map((_, index) => index); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default n => value => Array(n).fill(value); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => [...xs].reverse(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import reverse from "./reverse.js"; | ||
|
|
||
| export default predicate => xs => (predicate ? reverse(xs) : xs); | ||
przemyslawzalewski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| export default array => angle => { | ||
| const margin = Math.PI / 8; | ||
| const angleWithMargin = angle + margin; | ||
| const unit = Math.PI / 4; | ||
| const ratio = angleWithMargin / unit; | ||
| const offset = Math.floor(ratio); | ||
| return shift(offset)(array); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default ([, x]) => x; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => xs[xs.length - 2]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export default n => xs => | ||
| xs.map((_, index) => xs[(index + (n % xs.length) + xs.length) % xs.length]); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import shuffleInPlace from "./shuffleInPlace.js"; | ||
|
|
||
| export default xs => shuffleInPlace([...xs]); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| export default xs => { | ||
| for (let i = 0; i < xs.length; i++) { | ||
| const j = Math.floor(Math.random() * (i + 1)); | ||
| [xs[i], xs[j]] = [xs[j], xs[i]]; | ||
| } | ||
|
|
||
| return xs; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => xs.length === 1; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default f => xs => [...xs].sort(f); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| const add = (a, b) => a + b; | ||
|
|
||
| export default xs => xs.reduce(add, 0); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => Object.keys(xs[0]).map(key => [xs.map(x => x[key]), key]); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default xs => [...new Set(xs)]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import zipWith from "./zipWith.js"; | ||
|
|
||
| export default zipWith((x, y) => [x, y]); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default f => (xs, ys) => xs.map((x, index) => f(x, ys[index])); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| export default (f, wait) => { | ||
| let timeout; | ||
|
|
||
| return (...args) => { | ||
| const resolve = () => { | ||
| timeout = null; | ||
|
|
||
| f(...args); | ||
| }; | ||
|
|
||
| clearTimeout(timeout); | ||
|
|
||
| timeout = setTimeout(resolve, wait); | ||
| }; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export default duration => | ||
| new Promise(resolve => setTimeout(resolve, duration)); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import debounce from "./debounce.js"; | ||
| import delay from "./delay.js"; | ||
| import sequence from "./sequence.js"; | ||
|
|
||
| export { debounce, delay, sequence }; | ||
|
|
||
| export default { debounce, delay, sequence }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| export default async tasks => { | ||
| const results = tasks.map(_ => undefined); | ||
|
|
||
| await tasks.reduce((chain, current, i) => { | ||
| return chain.then(() => | ||
| current().then(x => { | ||
| results[i] = x; | ||
| return x; | ||
| }) | ||
| ); | ||
| }, Promise.resolve()); | ||
|
|
||
| return results; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| export default now => ( | ||
| { endedAt: aEnd, startedAt: aStart }, | ||
| { endedAt: bEnd, startedAt: bStart } | ||
| ) => { | ||
| const aEndDate = new Date(aEnd || now); | ||
| const aStartDate = new Date(aStart || now); | ||
| const bEndDate = new Date(bEnd || now); | ||
| const bStartDate = new Date(bStart || now); | ||
| const aEndDateValue = aEndDate.valueOf(); | ||
| const aStartDateValue = aStartDate.valueOf(); | ||
| const bEndDateValue = bEndDate.valueOf(); | ||
| const bStartDateValue = bStartDate.valueOf(); | ||
|
|
||
| const startDateDifference = aStartDateValue - bStartDateValue; | ||
| const startDatesEqual = startDateDifference === 0; | ||
|
|
||
| return startDatesEqual ? aEndDateValue - bEndDateValue : startDateDifference; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if the
anyis a good name for the function which checks if a provided array is not empty.Anyin many other languages do more than simplynot empty check. For example they check, if any element of the array meets the provided condition or checks if there is any not null and not false element.E.g:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JavaScript already have this as
Array.prototype.some. Theany(xs)call is equal to C#'sxs.Any()parameterless overload.The
some/everyare commonly used and well supported (IE9+) native Array APIs so IMHO no need to duplicate that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly :) As my first sentence in the comment: I'm thinking about the different name than
anyfor that methodThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I try to avoid
empty/isEmptyto avoid conflict with theemptydefinition ([]for array,{}for object). However, I consider dropping them to useemptyas a test function. But there is a naming issue of symmetric function -nonEmpty? I would like to avoid joined names and just stick with single-word names where possible. For now, it isanyandnone.One more thing, the functions handle missing argument case, so: any(null) = false, any(undefined) = false, any(0) = false, array.any([]) = false, object.any({}) = false etc.