{"id":13624711,"url":"https://github.com/skgmn/fromjs","last_synced_at":"2025-12-12T04:01:53.989Z","repository":{"id":8434977,"uuid":"10024589","full_name":"skgmn/fromjs","owner":"skgmn","description":"LINQ engine for JavaScript","archived":false,"fork":false,"pushed_at":"2014-04-08T06:04:35.000Z","size":2271,"stargazers_count":55,"open_issues_count":2,"forks_count":11,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-10-10T15:10:08.339Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skgmn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-05-13T04:57:14.000Z","updated_at":"2021-01-19T08:59:33.000Z","dependencies_parsed_at":"2022-09-14T08:51:26.139Z","dependency_job_id":null,"html_url":"https://github.com/skgmn/fromjs","commit_stats":null,"previous_names":["suckgamoni/fromjs","suckgamony/fromjs"],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skgmn%2Ffromjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skgmn%2Ffromjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skgmn%2Ffromjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skgmn%2Ffromjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skgmn","download_url":"https://codeload.github.com/skgmn/fromjs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223691736,"owners_count":17186875,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T21:01:45.435Z","updated_at":"2025-10-22T11:03:44.356Z","avatar_url":"https://github.com/skgmn.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# from.js\nfrom.js is a super fast, extremely-optimized LINQ engine for JavaScript.\n\n## Features\n* **High-performance** ([See the benchmark result](https://github.com/suckgamoni/fromjs/blob/work/web/benchmark/result.png))\n* Supports most LINQ functions that .NET provides\n* 100% lazy evaluation\n* Supports lambda expression\n\n## Supported platforms\n* Web\n* node.js\n\n## This is intended to\n\n* make it easy to use LINQ in JavaScript for whom is familiar with .NET environment.\n* provide LINQ features to JavaScript developers without worrying about performance.\n\n## Importing module\n\n**Web**\n\n```html\n\u003cscript src='from.js'\u003e\u003c/script\u003e\n```\n\n**node.js** (It can be installed by using _npm install fromjs_)\n\n```javascript\nvar from = require('fromjs');\n```\n## Basic iteration\n\nYou can basically iterate Array, String, Object by using each(). \n\n```javascript\nvar array = [1, 2, 3, 4];\nfrom(array).each(function (value, key) {\n    console.log('Value ' + value + ' at index ' + key);\n});\n\n// Value 1 at index 0\n// Value 2 at index 1\n// Value 3 at index 2\n// Value 4 at index 3\n```\n\n```javascript\nvar o = {foo: 1, bar: 2};\nfrom(o).each(function (value, key) {\n    console.log(key + ' = ' + value);\n});\n\n// foo = 1\n// bar = 2\n```\n\nAn iteration can be stopped by returning false.\n\n```javascript\nvar array = [1, 2, 3, 4];\nfrom(array).each(function (value, key) {\n    console.log('Value ' + value + ' at index ' + key);\n    return value != 2;\n});\n\n// Value 1 at index 0\n// Value 2 at index 1\n```\n\n_broken_ parameter can be used to investigate either the iteration was broken.\n\n```javascript\nvar array = [1, 2, 3, 4];\nvar broken = from(array).each(function (value, key) {\n    return value != 2;\n}).broken;\n\nconsole.log(broken); // true\n```\n\n## Basic query\n\n**Printing numbers less than 5 in an array**\n```javascript\nvar numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ]; \n\nfrom(numbers)\n    .where(function (value) {\n        return value \u003c 5;\n    })\n    .each(function (value) {\n        console.log(value);\n    });\n```\n\n**Printing each number + 1 in an array**\n```javascript\nvar numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ]; \n      \nfrom(numbers)\n    .select(function (value) {\n        return value + 1;\n    })\n    .each(function (value) {\n        console.log(value);\n    });\n```\n\n**Printing the average of top 3 grades**\n```javascript\nvar grades = [ 59, 82, 70, 56, 92, 98, 85 ];\n      \nvar average = from(grades)\n                .orderByDesc()\n                .take(3)\n                .average();\n                \nconsole.log(average);\n```\n\n## Lambda expression\n\nIt will be so tiring work to write every nested function every time. It can be evaded by using lambda expression.\nIts format is almost same as C#'s.\n\nHere's an example.\n\n```javascript\nfunction (arg1, arg2, arg3) {\n    return arg1 * arg2 + arg3;\n}\n```\n\nThe function given above can be re-written as below using lambda expression.\n\n```\n(arg1, arg2, arg3) =\u003e arg1 * arg2 + arg3\n```\n\nParentheses can be omitted when it has only one argument.\n\n```\narg1 =\u003e arg1 * 3\n```\n\nNow let's apply it into real JavaScript code.\n\n```javascript\nvar numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ]; \n\nfrom(numbers)\n    .where(function (value) {\n        return value \u003c 5;\n    })\n    .each(function (value) {\n        console.log(value);\n    });\n```\n\nThe example above can be re-written as below.\n\n```javascript\nvar numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ]; \n\nfrom(numbers)\n    .where('value =\u003e value \u003c 5')\n    .each('value =\u003e console.log(value)');\n```\n\n## Omitting argument list\n\nLambda expression can be shorten more by omitting argument list.\nBut how can it be used without any argument specified?\nfrom.js provides several abbreviations which can be used in this case.\n\n| Abbreviation | Meaning                          |\n| ------------ | -------------------------------- |\n| #n           | The _n_-th argument (zero based) |\n| $            | The first argument (same as #0)  |\n| $$           | The second argument (same as #1) |\n| @            | The last argument                |\n\nFor example,\n\n```\n(arg0, arg1, arg2, arg3) =\u003e arg0 * arg1 + arg2 * arg3\n```\n\nthe expression above can be shorten as below.\n\n```\n#0 * #1 + #2 * #3\n```\n\nor\n\n```\n$ * $$ + #2 * @\n```\n\nLet's apply it into JavaScript code.\n\n```javascript\nvar numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ]; \n\nfrom(numbers)\n    .where(function (value) {\n        return value \u003c 5;\n    })\n    .each(function (value) {\n        console.log(value);\n    });\n```\n\nThe sample above can be shorten as below.\n\n```javascript\nvar numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ]; \nfrom(numbers).where('$ \u003c 5').each('console.log($)');\n```\n\nAs you will see, most predicator functions have similar arguments list (except comparers).\nIn most cases, the first argument means 'value', the second means 'key', and the last means 'external argument'.\n(This is the most different part from .NET)\nYou can habitually consider $ as a value, $$ as a key, and @ as an external argument.\n\n## External argument\n\nBecause lambda expressions are given as String, any variables in the current context can't be referenced. For example,\n\n```javascript\nvar numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ]; \nvar n = 5;\nfrom(numbers).where('value =\u003e value \u003c n').each('value =\u003e console.log(value)');\n```\n\nthis code won't work. Then how can it be get around?\nMost predicator functions provided by from.js support external argument.\nIf an object is given as an external argument, it can be referenced in lambda expression.\n\nThe example above should be like this:\n\n```javascript\nvar numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ]; \nvar n = 5;\nfrom(numbers).where('(value, key, arg) =\u003e value \u003c arg', n).each('value =\u003e console.log(value)');\n// or simply\nfrom(numbers).where('$ \u003c @', n).each('console.log($)');\n```\n\n## Some more conveniences on lambda expression\n\nThere are still more chances to shorten lambda expressions.\n\n* 'Dot' can be omitted between $,$$,@ and following keyword. For instance, _$length_ will be processed identically as _$.length_.\n\n```javascript\n// Print fruit names ordered by its length\nvar fruits = [ \"apple\", \"passionfruit\", \"banana\", \"mango\",\n    \"orange\", \"blueberry\", \"grape\", \"strawberry\" ];\nfrom(fruits).orderBy('$length').each('console.log($)');\n```\n\n* Referencing array of $,$$,@ can be shorten like this: @[3] --\u003e @3\n\n```javascript\nvar fruits = [ \"apple\", \"passionfruit\", \"banana\", \"mango\",\n    \"orange\", \"blueberry\", \"grape\", \"strawberry\" ];\nvar appleOrBanana = from(fruits).count('$ == @0 || $ == @1', ['apple', 'banana']);\nconsole.log(appleOrBanana); // 2\n```\n\n## Empty iterable\n\n Sometimes it is needed to use an empty iterable object. In this case, simply call from() without any argument,\n\n```javascript\nvar names1 = [ \"Hartono, Tommy\" ];\nvar names2 = [ \"Adams, Terry\", \"Andersen, Henriette Thaulow\", \"Hedlund, Magnus\", \"Ito, Shu\" ];\nvar names3 = [ \"Solanki, Ajay\", \"Hoeing, Helge\", \"Andersen, Henriette Thaulow\", \"Potra, Cristina\", \"Iallo, Lucio\" ];\n\nvar namesList = [ names1, names2, names3 ];\n\n// Only include arrays that have four or more elements\nfrom(namesList)\n    .aggregate(from(), \"(current, next) =\u003e next.length \u003e 3 ? current.union(next) : current\")\n    .each(\"console.log($)\");\n    \n/*\n This code produces the following output:\n\n Adams, Terry\n Andersen, Henriette Thaulow\n Hedlund, Magnus\n Ito, Shu\n Solanki, Ajay\n Hoeing, Helge\n Potra, Cristina\n Iallo, Lucio\n*/\n```\n\n## Ranged iterable\n\n It is able to generate a ranged iterable by using from.range().\n \n```javascript\nfrom.range(n)                // from 0 to n - 1\nfrom.range(start, end)       // from start to end - 1\nfrom.range(start, end, step) // from start to end - 1, increasing by step\n```\n\n```javascript\nfrom.range(4)\n    .select(\"$ * $\")\n    .each(\"console.log($)\");\n\n/*\n This code produces the following output:\n 0\n 1\n 4\n 9\n*/\n```\n\n```javascript\n// Generate a sequence of three integers starting at 4, \n// and then select their squares.\nfrom.range(4, 7)\n    .select(\"$ * $\")\n    .each(\"console.log($)\");\n\n/*\n This code produces the following output:\n 16\n 25\n 36\n*/\n```\n\n```javascript\nfrom.range(3, 13, 3)\n    .select(\"$ * $\")\n    .each(\"console.log($)\");\n\n/*\n This code produces the following output:\n 9\n 36\n 81\n 144\n*/\n```\n\n## Repeator\n\n```javascript\nconsole.log(from.repeat('a', 4).toString());\n\n/*\n This code produces the following output:\n aaaa\n*/\n```\n\n## Regular expression iteration\n\n```javascript\nvar myRe = /ab*/g;\nvar str = \"abbcdefabh\";\n\nfrom(myRe).match(str)\n    .each(function (m) {\n        console.log('Found ' + m +\n            '. Next match starts at ' + (m.index + m[0].length));\n    });\n\n/*\n This code produces the following output:\n\n  Found abb. Next match starts at 3\n  Found ab. Next match starts at 9\n*/\n```\n\n```javascript\nvar str = 'Hello world!';\nconsole.log(from(/Hello/g).match(str).any()); // true\nconsole.log(from(/Hello/g, str).any()); // true\n\nconsole.log(from(/W3Schools/g, str).any()); // false\n```\n\n## Supported queries\n\n* [aggregate](https://github.com/suckgamoni/fromjs/wiki/aggregate(seed, func[, arg]%29)\n* [all](https://github.com/suckgamoni/fromjs/wiki/all(predicate[, arg]%29)\n* [any](https://github.com/suckgamoni/fromjs/wiki/any([predicate, arg]%29)\n* [at](https://github.com/suckgamoni/fromjs/wiki/at(index%29)\n* [atOrDefault](https://github.com/suckgamoni/fromjs/wiki/atOrDefault(index, defValue%29)\n* [average](https://github.com/suckgamoni/fromjs/wiki/average(%29)\n* [concat](https://github.com/suckgamoni/fromjs/wiki/concat(second%29)\n* [contains](https://github.com/suckgamoni/fromjs/wiki/contains(value[, comparer, arg]%29)\n* [count](https://github.com/suckgamoni/fromjs/wiki/count([predicate, arg]%29)\n* [defaultIfEmpty](https://github.com/suckgamoni/fromjs/wiki/defaultIfEmpty(defValue%29)\n* [distinct](https://github.com/suckgamoni/fromjs/wiki/distinct([comparer, arg]%29)\n* [except](https://github.com/suckgamoni/fromjs/wiki/except(second[, comparer, arg]%29)\n* [first](https://github.com/suckgamoni/fromjs/wiki/first([predicate, arg]%29)\n* [firstOrDefault](https://github.com/suckgamoni/fromjs/wiki/firstOrDefault(defValue%29 , firstOrDefault(predicate, defValue[, arg]%29)\n* [groupBy](https://github.com/suckgamoni/fromjs/wiki/groupBy(selectors[, comparer, arg]%29)\n* [groupJoin](https://github.com/suckgamoni/fromjs/wiki/groupJoin(inner, outerKeySelector, innerKeySelector, resultSelector[, comparer, arg]%29)\n* [intersect](https://github.com/suckgamoni/fromjs/wiki/intersect(second[, comparer, arg]%29)\n* [join](https://github.com/suckgamoni/fromjs/wiki/join(inner, outerKeySelector, innerKeySelector, resultSelector[, comparer, arg]%29)\n* [last](https://github.com/suckgamoni/fromjs/wiki/last([predicate, arg]%29)\n* [lastOrDefault](https://github.com/suckgamoni/fromjs/wiki/lastOrDefault(defValue%29 , lastOrDefault(predicate, defValue[, arg]%29)\n* [max](https://github.com/suckgamoni/fromjs/wiki/max([selector, arg]%29)\n* [min](https://github.com/suckgamoni/fromjs/wiki/min([selector, arg]%29)\n* [orderBy](https://github.com/suckgamoni/fromjs/wiki/orderBy(keySelector[, comparer, arg]%29)\n* [orderByDesc](https://github.com/suckgamoni/fromjs/wiki/orderByDesc(keySelector[, comparer, arg]%29)\n* [reverse](https://github.com/suckgamoni/fromjs/wiki/reverse(%29)\n* [select](https://github.com/suckgamoni/fromjs/wiki/select(selector[, arg]%29)\n* [selectMany](https://github.com/suckgamoni/fromjs/wiki/selectMany(selector[, arg]%29)\n* [selectPair](https://github.com/suckgamoni/fromjs/wiki/selectPair(valueSelector, keySelector[, arg]%29)\n* [sequenceEqual](https://github.com/suckgamoni/fromjs/wiki/sequenceEqual(second[, comparer, arg]%29)\n* [single](https://github.com/suckgamoni/fromjs/wiki/single([predicate, arg]%29)\n* [singleOrDefault](https://github.com/suckgamoni/fromjs/wiki/singleOrDefault(defValue%29 , singleOrDefault(predicate, defValue[, arg]%29)\n* [skip](https://github.com/suckgamoni/fromjs/wiki/skip(count%29)\n* [skipWhile](https://github.com/suckgamoni/fromjs/wiki/skipWhile(predicate[, arg]%29)\n* [sum](https://github.com/suckgamoni/fromjs/wiki/sum(%29)\n* [take](https://github.com/suckgamoni/fromjs/wiki/take(count%29)\n* [takeWhile](https://github.com/suckgamoni/fromjs/wiki/takeWhile(predicate[, arg]%29)\n* [thenBy](https://github.com/suckgamoni/fromjs/wiki/thenBy(keySelector[, comparer, arg]%29)\n* [thenByDesc](https://github.com/suckgamoni/fromjs/wiki/thenByDesc(keySelector[, comparer, arg]%29)\n* [toArray](https://github.com/suckgamoni/fromjs/wiki/toArray(%29)\n* [toJSON](https://github.com/suckgamoni/fromjs/wiki/toJSON(%29)\n* [toString](https://github.com/suckgamoni/fromjs/wiki/toString([separator]%29)\n* [toURLEncoded](https://github.com/suckgamoni/fromjs/wiki/toURLEncoded(%29)\n* [trim](https://github.com/suckgamoni/fromjs/wiki/trim([left, right, arg]%29)\n* [union](https://github.com/suckgamoni/fromjs/wiki/union(second[, comparer, arg]%29)\n* [where](https://github.com/suckgamoni/fromjs/wiki/where(predicate[, arg]%29)\n* [zip](https://github.com/suckgamoni/fromjs/wiki/zip(second, resultSelector[, arg]%29)\n\n## Some practical examples\n\n```javascript\n// Determine either n is a prime number.\nfunction isPrime(n) {\n    return n == 2 ||\n        (n % 2 == 1 \u0026\u0026\n        !from.range(3, n, 2)\n            .takeWhile('$ * $ \u003c= @', n)\n            .any('@ % $ == 0', n));\n}\n\n// Get prime numbers bigger than n.\n// Returns [count] numbers in a array, or a single number if count is zero.\nfunction getPrimeBiggerThan(n, count) {\n    n = parseInt(n) + 1;\n    if (n % 2 == 0) ++n;\n\n    var query = from.range(n, Infinity, 2).where('@($)', isPrime);\n    if (!count) {\n        return query.first();\n    } else {\n        return query.take(count).toArray();\n    }\n}\n\nconsole.log(getPrimeBiggerThan(10, 5));\n\n// [ 11, 13, 17, 19, 23 ]\n```\n\n```javascript\nfunction splitTrimmed(s, delimiter) {\n    return from(s.split(delimiter))\n                .select('from($).trim().toString()')\n                .where('$length \u003e 0')\n                .toArray();\n}\n\nvar s = splitTrimmed('  a |  b  |  c  |  |  d  |  |  ', '|');\nconsole.log(s);\n\n// [ 'a', 'b', 'c', 'd' ]\n```\n\n```javascript\nvar array = [1, 2, 3];\n\n// Make a shallow copy of a array\nvar copy = from(array).toArray();\n\narray.push(4);\nconsole.log(copy);\n// [ 1, 2, 3 ]\n```\n\n## License\n\nThis software uses MIT license.\n\n```\nCopyright 2012-2013 suckgamony@gmail.com\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskgmn%2Ffromjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskgmn%2Ffromjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskgmn%2Ffromjs/lists"}