https://github.com/wm123450405/linqjs
https://gitee.com/wm123450405/linqjs (国内)
- 对 JavaScript 中原生数组、对象进行扩展, 提供了一些对数据的操作方法.
- 包括对数组结构、树形结构、对象结构等数据进行 查询,排序,连接,合并,分组,分段,转换,遍历 等一系列功能.
- 可以用精炼和易懂的代码实现比较复杂的操作
let array = [ 'zhao', 'qian', 'sun', 'li', 'zhou', 'wu', 'zheng', 'wang' ]
//将上述数组按照字母长度进行排序, 字母长度一致的按照字母顺序倒序排序
console.log(array.asEnumerable().orderBy(str => str.length).thenByDescending().toArray());
//结果为
//wu,li,sun,zhou,zhao,wang,qian,zheng
//一些人
let magnus = { name: "Hedlund, Magnus" },
terry = { name: "Adams, Terry" },
charlotte = { name: "Weiss, Charlotte" };
//一些宠物
let barley = { name: "Barley", owner: "Adams, Terry" },
boots = { name: "Boots", owner: "Adams, Terry" },
whiskers = { name: "Whiskers", owner: "Weiss, Charlotte" },
daisy = { name: "Daisy", owner: "Hedlund, Magnus" };
//一个包含所有 人 的数组
let people = [ magnus, terry, charlotte ];
//一个包含所有 宠物 的数组
let pets = [ barley, boots, whiskers, daisy ];
//这是一个一对多关系的两个数组
//需要显示出来所有的 人-宠物 的关系信息
//传统做法是
for (let p of people) {
for (let pet of pets) {
if (pet.owner === p.name) {
console.log(`${ p.name } - ${ pet.name }`);
}
}
}
//使用我的工具是
//思想类似数据库查询(如下语句), 连接两个数组(表), 条件为 person 的 name 与 pet 的 owner 相等
//select person.name, pet.name from `people` as person join `pets` as pet on person.name = pet.owner
people.asEnumerable()
.join(pets, (person, pet) =>`${ person.name} - ${ pet.name}`,
person => person.name,
pet => pet.owner)
.forEach(res => console.log(res));
//这是一个树形结构
let tree = {
value: 'a',
children: [
{
value: 'b', //此节点为 节点 c 与 节点 f 的最小公共祖先
children: [
{ value: 'c' },
{
value: 'd',
children: [
{ value: 'e' },
{ value: 'f' },
{ value: 'g' },
]
}
]
},
{ value: 'h', }
]
};
//获取一个树形的中多个节点的最小公共祖先
let root = tree.asEnumerable(node => node.children, node => node.value);
console.log(root.lowestAncestor('c', 'f')); //结果是 b
更多用法及案例 希望大家进入文档查看 http://wm123450405.oschina.io/linqjs/#/zh-cn
望大家多多关注 并给于意见和指导 谢谢
1
wm123450405 OP 一开始,在 ES5 的时代,我觉得 js 对数组的操作实在太繁琐了. 可能正是这种繁琐才有了像 underscore 这样优秀的 js 库的出现.
我本不是做前端出身的,我觉得其他语言对于数组或列表的操作要比 js 好用很多,提供了大量的方法和功能. 于是最早参考的 C#中的功能实现了一些方法. 后来,ES6 发布并普及开来,js 原生数组也增加了很多好用的功能,但是这还远远不够. 于是我又翻出了我的代码用 ES6 重写.这一次我又借鉴了另外一些语言中的部分特性,比如 php.我想我后面可能再会添加一些其他语言类似的功能,比如 Java 等. 后来我在 stackoverflow 中看到很多人对于树形结构的操作提了很多的问题,我像我的工具包应该要可以为他们提供帮助.于是在最新的几个版本中我加入了对树形结构的一些操作. 我想现在这个工具包应该算比较稳定了. 所以我发上来希望和大家交流交流. 也希望能学到更多的东西. |
2
codermagefox 2018-03-29 16:22:11 +08:00
楼主你好,请问我能抄一个自己做实现吗?
|
3
per 2018-03-29 16:51:40 +08:00 via iPhone
@wm123450405 没看代码,不过你这个是在数据类型的 prototype 上修改的吗?
|
4
wm123450405 OP @per 是的 在 prototype 上做了扩展的
|
5
wm123450405 OP @codermagefox 可以啊 我也是造了一些轮子而已
|
6
codermagefox 2018-03-29 17:03:07 +08:00 1
@wm123450405 #5 准备看完 underscore 再来看你这个,然后自己撸个试试。感谢,已 star
|
7
per 2018-03-29 18:04:32 +08:00 via iPhone
@wm123450405 那我这里有个问题,比如一个数组是由一个类 A 实例化得到的,然后这个 A 也是继承于其他类,那当访问你的这个方法的时候会通过原型链一层层往上找,考虑过开销嘛?
|
8
crs0910 2018-03-29 18:17:59 +08:00 2
|
9
wm123450405 OP @per 不好意思 不是很明白你想表达的意思 你可以举例说明下嘛 我这里只是扩展了 Array 类 用 Array.prototype 的方式
|
10
wm123450405 OP @crs0910 你是让我看看 mootools 这个库吗? 如果你希望的只是类似 flatMap 这样的展开一个包含数组元素的数组 在我的库里是 selectMany
|
11
zenxds 2018-03-29 18:48:18 +08:00 1
改原生数组的原型后患无穷,ES 标准里的一些方法名那么奇怪就是因为当年 prototype.js 的遗留才不得不改名
|
12
wm123450405 OP @zenxds 我的库默认只会在 Array 上注册一个 asEnumerable 方法 用来获取一个 IEnumerable 对象进行后续操作 当然也可以开启对 Array 的直接扩展 主要看你有没有用到其他有冲突的库
|
13
per 2018-03-29 18:57:01 +08:00 1
@wm123450405 我表达的不是很清楚,你可以看一下 MDN 上的解释。不过还是给你点个星
|
14
per 2018-03-29 18:57:12 +08:00
|
15
wm123450405 OP @per 感谢你提供的信息. 我想我在编写这个库的时候并没有考虑这一层面的性能问题.
首先你分享的文章我不是特别的明白 我理解的大概含义 一般的 js 引擎会对已有的对象的属性查找进行优化 会将属性按照某种顺序排列在内存中 并生成一个身份(shape 或 structure ID) 如果修改 prototype 的话 会打乱这种顺序 导致原本可以快速查找属性的功能失效 造成性能损失 就你一共提出的问题 我想: 如果说因为原型链比较深导致其查找 property 比较慢的话 我想这个应该不容易避免 因为原型链的深度是受类型的继承关系的影响 如果是因为修改 prototype 导致 js 引擎在做优化时不能达到最佳性能的话 我目前也没有更好的解决办法 |
16
wm123450405 OP 首先感谢各位的关注 如果大家发现有什么问题或者有什么希望加入的功能 欢迎大家在此回复 或者直接在 github/gitee 上提 issue 给我
|
17
raphaelsoul 2018-04-02 09:47:51 +08:00 1
拒绝修改原生数据类型的库:(
|
18
narcotics 2018-04-02 14:30:24 +08:00 via Android 1
lodash 的做法是用 _.chain 做一层包装,再实现链式操作,最后用 _.value 做"拆箱"
总之改变原生原型不是个好实践 |
19
wm123450405 OP 回复 楼上 2 位
首先 我的库里目前只对原生对象扩展了 asEnumerable 一个方法. 就是尽量避免冲突 其次 库也支持 Enumerable(source)的方式获取一个和 source.asEnumerable()一样的结果, 类似 lodash 的 chain. 再使用 toArray 等方法生成最终结果. 当然 如果大家觉得修改原生原型的做法确实不合适 我想也我会在后面的版本中修改 /删除这种方式 |