ramda 函数 list

原文链接: ramda 函数 list

上一篇: ramda 函数 Object

下一篇: ramda 函数 relation type

函数是那个分类下的取决于其输入的数据类型, 而非输出类型

const R = require('ramda')

// adjust
// 将数组中指定索引处的值替换为经函数变换的值。
R.adjust(1, R.toUpper, ['a', 'b', 'c', 'd']);      //=> ['a', 'B', 'c', 'd']
R.adjust(-1, R.toUpper, ['a', 'b', 'c', 'd']);     //=> ['a', 'b', 'c', 'D']

// all
// 如果列表中的所有元素都满足 predicate,则返回 true;否则,返回 false。
// 若第二个参数自身存在 all 方法,则调用自身的 all 方法。
// 若在列表位置中给出 transfomer,则用作 transducer 。
const equals3 = R.equals(3);
R.all(equals3)([3, 3, 3, 3]); //=> true
R.all(equals3)([3, 3, 1, 3]); //=> false

// any
// 只要列表中有一个元素满足 predicate,就返回 true,否则返回 false。
// 若第二个参数自身存在 any 方法,则调用其自身的 any。
// 若在列表位置中给出 transfomer,则用作 transducer 。
const lessThan0 = R.flip(R.lt)(0);
const lessThan2 = R.flip(R.lt)(2);
R.any(lessThan0)([1, 2]); //=> false
R.any(lessThan2)([1, 2]); //=> true

// aperture
// 返回一个新列表,列表中的元素为由原列表相邻元素组成的 n 元组。如果 n 大于列表的长度,则返回空列表。
// 若在列表位置中给出 transfomer,则用作 transducer 。
R.aperture(2, [1, 2, 3, 4, 5]); //=> [[1, 2], [2, 3], [3, 4], [4, 5]]
R.aperture(3, [1, 2, 3, 4, 5]); //=> [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
R.aperture(7, [1, 2, 3, 4, 5]); //=> []

// append
// 在列表末尾拼接一个元素。
R.append('tests', ['write', 'more']); //=> ['write', 'more', 'tests']
R.append('tests', []); //=> ['tests']
R.append(['tests'], ['write', 'more']); //=> ['write', 'more', ['tests']]

// chain
// chain 将函数映射到列表中每个元素,并将结果连接起来。 chain 在一些库中也称为 flatMap(先 map 再 flatten )。
// 若第二个参数存在 chain 方法,则调用其自身的 chain方法。该参数需符合 FantasyLand Chain 规范。
// 如果第二个参数是函数,chain(f, g)(x) 等价于 f(g(x), x)。
// 若在列表位置中给出 transfomer,则用作 transducer。
const duplicate = n => [n, n];
R.chain(duplicate, [1, 2, 3]); //=> [1, 1, 2, 2, 3, 3]
R.chain(R.append, R.head)([1, 2, 3]); //=> [1, 2, 3, 1]

// concat
// 连接列表或字符串。
// 注意:不同于 Array.prototype.concat, R.concat 要求两个参数类型相同。 如果将 Array 与非 Array 连接,将抛出错误。
// 若第一个参数自身存在 concat 方法,则调用自身的 concat。
// 也可以用于连接 符合 fantasy-land 半群 类型的两个实例。
R.concat('ABC', 'DEF'); // 'ABCDEF'
R.concat([4, 5, 6], [1, 2, 3]); //=> [4, 5, 6, 1, 2, 3]
R.concat([], []); //=> []

// contains 已经废弃
// 只要列表中有一个元素等于指定值,则返回 true;否则返回 false。通过 R.equals 函数进行相等性判断。
// 也可以判断字符串中是否包含指定值。
R.contains(3, [1, 2, 3]); //=> true
R.contains(4, [1, 2, 3]); //=> false
R.contains({name: 'Fred'}, [{name: 'Fred'}]); //=> true
R.contains([42], [[42]]); //=> true
R.contains('ba', 'banana'); //=>true

// drop
// 删除给定 list,string 或者 transducer/transformer(或者具有 drop 方法的对象)的前 n 个元素。
// 若第二个参数自身存在 drop 方法,则调用自身的 drop 方法。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
R.drop(1, ['foo', 'bar', 'baz']); //=> ['bar', 'baz']
R.drop(2, ['foo', 'bar', 'baz']); //=> ['baz']
R.drop(3, ['foo', 'bar', 'baz']); //=> []
R.drop(4, ['foo', 'bar', 'baz']); //=> []
R.drop(3, 'ramda');               //=> 'da'

// dropLast
// 删除 "list" 末尾的 n 个元素。
// 若在列表位置中给出 transfomer,则用作 transducer 。
R.dropLast(1, ['foo', 'bar', 'baz']); //=> ['foo', 'bar']
R.dropLast(2, ['foo', 'bar', 'baz']); //=> ['foo']
R.dropLast(3, ['foo', 'bar', 'baz']); //=> []
R.dropLast(4, ['foo', 'bar', 'baz']); //=> []
R.dropLast(3, 'ramda');               //=> 'ra'

// dropLastWhile
// 对 list 从后向前一直删除满足 predicate 的尾部元素,直到遇到第一个 falsy 值,此时停止删除操作。
// predicate 需要作为第一个参数传入。
// 若在列表位置中给出 transfomer,则用作 transducer 。
const lteThree = x => x <= 3;
R.dropLastWhile(lteThree, [1, 2, 3, 4, 3, 2, 1]); //=> [1, 2, 3, 4]
R.dropLastWhile(x => x !== 'd', 'Ramda'); //=> 'Ramd'

// dropRepeats
// 返回一个没有连续重复元素的 list。通过 R.equals 函数进行相等性判断。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
R.dropRepeats([1, 1, 1, 2, 3, 4, 4, 2, 2]); //=> [1, 2, 3, 4, 2]

// dropRepeatsWith
// 返回一个没有连续重复元素的 list。首个参数提供的 predicate 用于检测 list 中相邻的两个元素是否相等。一系列相等元素中的首个元素会被保留。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
const l = [1, -1, 1, 3, 4, -4, -4, -5, 5, 3, 3];
R.dropRepeatsWith(R.eqBy(Math.abs), l); //=> [1, 3, 4, -5, 3]


// dropWhile
// 对 list 从前向后删除满足 predicate 的头部元素,直到遇到第一个 falsy 值。
// predicate 需要作为第一个参数传入。
// 若第二个参数自身存在 dropWhile 方法,则调用自身的 dropWhile 方法。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
const lteTwo = x => x <= 2;
R.dropWhile(lteTwo, [1, 2, 3, 4, 3, 2, 1]); //=> [3, 4, 3, 2, 1]
R.dropWhile(x => x !== 'd', 'Ramda'); //=> 'da'

// endsWith
// 检查列表是否以指定的子列表结尾。
// 同样的,检查字符串是否以指定的子字符串结尾。
R.endsWith('c', 'abc')                //=> true
R.endsWith('b', 'abc')                //=> false
R.endsWith(['c'], ['a', 'b', 'c'])    //=> true
R.endsWith(['b'], ['a', 'b', 'c'])    //=> false


// filter
// 使用 predicate 遍历传入的 Filterable,返回满足 predicate 的所有元素的新的 Filterable。新 Filterable 与原先的类型相同。Filterable 类型包括 plain object 或者任何带有 filter 方法的类型,如 Array 。
// 若第二个参数自身存在 filter 方法,则调用自身的 filter 方法。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
const isEven = n => n % 2 === 0;
R.filter(isEven, [1, 2, 3, 4]); //=> [2, 4]
R.filter(isEven, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}

// find
// 查找并返回 list 中首个满足 predicate 的元素;如果未找到满足条件的元素,则返回 undefined 。
// 若第二个参数自身存在 find 方法,则调用自身的 find 方法。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
const xs = [{a: 1}, {a: 2}, {a: 3}];
R.find(R.propEq('a', 2))(xs); //=> {a: 2}
R.find(R.propEq('a', 4))(xs); //=> undefined

// findIndex
// 查找并返回 list 中首个满足 predicate 的元素的索引;如果未找到满足条件的元素,则返回 -1 。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
const xs2 = [{a: 1}, {a: 2}, {a: 3}];
R.findIndex(R.propEq('a', 2))(xs2); //=> 1
R.findIndex(R.propEq('a', 4))(xs2); //=> -1

// findLast
// 查找并返回 list 中最后一个满足 predicate 的元素;如果未找到满足条件的元素,则返回 undefined 。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
const xs3 = [{a: 1, b: 0}, {a: 1, b: 1}];
R.findLast(R.propEq('a', 1))(xs3); //=> {a: 1, b: 1}
R.findLast(R.propEq('a', 4))(xs3); //=> undefined


// findLastIndex
// 查找并返回 list 中最后一个满足 predicate 的元素的索引;如果未找到满足条件的元素,则返回 -1 。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
const xs4 = [{a: 1, b: 0}, {a: 1, b: 1}];
R.findLastIndex(R.propEq('a', 1))(xs4); //=> 1
R.findLastIndex(R.propEq('a', 4))(xs4); //=> -1

// flatten
// 获取 list 的所有元素(包含所有子数组中的元素),然后由这些元素组成一个新的数组。深度优先。
R.flatten([1, 2, [3, 4], 5, [6, [7, 8, [9, [10, 11], 12]]]]);

// forEach
// 遍历 list,对 list 中的每个元素执行方法 fn。
// fn 接收单个参数: (value)。
// 注意: R.forEach 并不会跳过已删除的或者未赋值的索引(sparse arrays)
// 这一点和原生的 Array.prototype.forEach 方法不同. 获取更多相关信息,
// 请查阅: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Description
// 还要注意, 不同于 Array.prototype.forEach,
// Ramda 的 forEach 会将原数组返回。在某些库中,该方法也被称为 each.
// 若第二个参数自身存在 forEach 方法,则调用自身的 forEach 方法。
const printXPlusFive = x => console.log(x + 5);
R.forEach(printXPlusFive, [1, 2, 3]); //=> [1, 2, 3]
// logs 6
// logs 7
// logs 8

// fromPairs
// 由一系列 “键值对” 创建一个 object。如果某个键出现多次,选取最右侧的键值对。
R.fromPairs([['a', 1], ['b', 2], ['c', 3]]); //=> {a: 1, b: 2, c: 3}

// groupBy
// 将列表根据一定规则拆分成多组子列表,并存储在一个对象中。
// 对列表中的每个元素调用函数,根据函数返回结果进行分组。函数返回字符串作为相等性判断,返回的字符串作为存储对象的键,具有相同返回字符串的元素聚合为数组,作为该键的值。
// 若第二个参数自身存在 groupBy 方法,则调用自身的 groupBy 方法。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
const byGrade = R.groupBy(function (student) {
  const score = student.score;
  return score < 65 ? 'F' :
    score < 70 ? 'D' :
      score < 80 ? 'C' :
        score < 90 ? 'B' : 'A';
});
const students = [{name: 'Abby', score: 84},
  {name: 'Eddy', score: 58},
  // ...
  {name: 'Jack', score: 69}];
byGrade(students);
// {
//   'A': [{name: 'Dianne', score: 99}],
//   'B': [{name: 'Abby', score: 84}]
//   // ...,
//   'F': [{name: 'Eddy', score: 58}]
// }


// groupWith
// 通过给定的对比函数,将列表按顺序分割成多组子列表。
// 对比函数只比较相邻元素。
R.groupWith(R.equals, [0, 1, 1, 2, 3, 5, 8, 13, 21])
//=> [[0], [1, 1], [2], [3], [5], [8], [13], [21]]
R.groupWith((a, b) => a + 1 === b, [0, 1, 1, 2, 3, 5, 8, 13, 21])
//=> [[0, 1], [1, 2, 3], [5], [8], [13], [21]]
R.groupWith((a, b) => a % 2 === b % 2, [0, 1, 1, 2, 3, 5, 8, 13, 21])
//=> [[0], [1, 1], [2], [3, 5], [8], [13, 21]]
R.groupWith(R.eqBy(isVowel), 'aestiou')
//=> ['ae', 'st', 'iou']

// head
// 求列表或字符串的首个元素。在某些库中,该函数也被称作 first。
R.head(['fi', 'fo', 'fum']); //=> 'fi'
R.head([]); //=> undefined
R.head('abc'); //=> 'a'
R.head(''); //=> ''

// includes
// 只要列表中有一个元素等于指定值,则返回 true;否则返回 false。通过 R.equals 函数进行相等性判断。
// 也可以判断字符串中是否包含指定值。
R.includes(3, [1, 2, 3]); //=> true
R.includes(4, [1, 2, 3]); //=> false
R.includes({name: 'Fred'}, [{name: 'Fred'}]); //=> true
R.includes([42], [[42]]); //=> true
R.includes('ba', 'banana'); //=>true

// indexBy
// 通过生成键的函数,将元素为对象的 list 转换为以生成的键为索引的新对象。
// 注意,如果 list 中多个对象元素生成相同的键,以最后一个对象元素作为该键的值。
// 若在 list 位置中给出 transfomer ,则用作 transducer 。
const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}];
R.indexBy(R.prop('id'), list);
//=> {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}}

// indexOf
// 返回给定元素在数组中首次出现时的索引值,如果数组中没有该元素,则返回 -1。通过 R.equals 函数进行相等性判断。
R.indexOf(3, [1, 2, 3, 4]); //=> 2
R.indexOf(10, [1, 2, 3, 4]); //=> -1


// init
// 返回 list 或 string 删除最后一个元素后的部分。
R.init([1, 2, 3]);  //=> [1, 2]
R.init([1, 2]);     //=> [1]
R.init([1]);        //=> []
R.init([]);         //=> []
R.init('abc');  //=> 'ab'
R.init('ab');   //=> 'a'
R.init('a');    //=> ''
R.init('');     //=> ''

// insert
// 将元素插入到 list 指定索引处。注意,该函数是非破坏性的:返回处理后列表的拷贝。函数运行过程中不会破坏任何列表。
R.insert(2, 'x', [1, 2, 3, 4]); //=> [1,2,'x',3,4]

// insertAll
// 将子 list 插入到 list 指定索引处。注意,该函数是非破坏性的:返回处理后列表的拷贝。函数运行过程中不会破坏任何列表。
R.insertAll(2, ['x', 'y', 'z'], [1, 2, 3, 4]); //=> [1,2,'x','y','z',3,4]

// intersperse
// 在列表的元素之间插入分割元素。
// 若第二个参数自身存在 intersperse 方法,则调用自身的 intersperse 方法。
R.intersperse('a', ['b', 'n', 'n', 's']); //=> ['b', 'a', 'n', 'a', 'n', 'a', 's']

// into
// 使用 transducer 对 list 中的元素进行转换,然后使用基于 accumulator 的类型的迭代器函数将转换后的元素依次添加到 accumulator 上。
// accumulator 的类型可以是:array、string、object 或者 transformer 。
// 如果 accumulator 类型是 array 或 string,则迭代元素将被添加到数组或连接到字符串上;
// 如果是对象,迭代元素将会被直接合并;如果是二元素数组,迭代元素会以键值对形式进行合并。
// accumulator 也可作为 transformer 对象,
// 提供 transformer 所需要的二元 reducing iterator、step、零元 init 和 一元 result 函数。
// step 作为 reduce 过程中的迭代函数;result 将最终的 accumulator 转换为需要的返回类型(通常为 R.identity);
// init 提供初始 accumulator。
// 在 transducer 初始化之后,使用 R.reduce 进行迭代操作。
const numbers = [1, 2, 3, 4];
const transducer = R.compose(R.map(R.add(1)), R.take(2));
R.into([], transducer, numbers); //=> [2, 3]
const intoArray = R.into([]);
intoArray(transducer, numbers); //=> [2, 3]

const R = require('ramda')

// join
// 将列表中所有元素通过 分隔符 串连为一个字符串。
const spacer = R.join(' ');
spacer(['a', 2, 3.4]);   //=> 'a 2 3.4'
R.join('|', [1, 2, 3]);    //=> '1|2|3'

// last
// 返回列表或字符串的最后一个元素。
R.last(['fi', 'fo', 'fum']); //=> 'fum'
R.last([]); //=> undefined
R.last('abc'); //=> 'c'
R.last(''); //=> ''

// lastIndexOf
// 返回数组中某元素最后一次出现的位置,如果数组中不包含该项则返回 -1 。通过 R.equals 函数进行相等性判断。
R.lastIndexOf(3, [-1, 3, 3, 0, 1, 2, 3, 4]); //=> 6
R.lastIndexOf(10, [1, 2, 3, 4]); //=> -1

// length
// 通过 list.length,返回数组的大小(数组中元素的数量)。
R.length([]); //=> 0
R.length([1, 2, 3]); //=> 3

// map
// 接收一个函数和一个 functor, 将该函数应用到 functor 的每个值上,返回一个具有相同形态的 functor。
// Ramda 为 Array 和 Object 提供了合适的 map 实现,因此 R.map 适用于 [1, 2, 3] 或 {x: 1, y: 2, z: 3}。
// 若第二个参数自身存在 map 方法,则调用自身的 map 方法。
// 若在列表位置中给出 transfomer,则用作 transducer 。
// 函数也是 functors,map 会将它们组合起来(相当于 R.compose)。
const double = x => x * 2;
R.map(double, [1, 2, 3]); //=> [2, 4, 6]
R.map(double, {x: 1, y: 2, z: 3}); //=> {x: 2, y: 4, z: 6}


// mapAccum
// mapAccum 的行为类似于 map 和 reduce 的组合;它将迭代函数作用于列表中的每个元素,
// 从左往右传递经迭代函数计算的累积值,并将最后的累积值和由所有中间的累积值组成的列表一起返回。
// 迭代函数接收两个参数,acc 和 value, 返回一个元组 [acc, value]。
const digits = ['1', '2', '3', '4'];
const appender = (a, b) => [a + b, a + b];
R.mapAccum(appender, 0, digits); //=> ['01234', ['01', '012', '0123', '01234']]

// mapAccumRight
// mapAccumRight 的行为类似于 map 和 reduce 的组合
// ;它将迭代函数作用于列表中的每个元素,从右往左传递经迭代函数计算的累积值,
// 并将最后的累积值和由所有中间的累积值组成的列表一起返回。
// 和 mapAccum 类似,除了列表遍历顺序是从右往左的。
// 迭代函数接收两个参数,acc 和 value ,返回一个元组 [acc, value]。
const digits2 = ['1', '2', '3', '4'];
const appender2 = (a, b) => [b + a, b + a];
R.mapAccumRight(appender2, 5, digits2); //=> ['12345', ['12345', '2345', '345', '45']]

// mergeAll
// 将对象类型列表合并为一个对象。
R.mergeAll([{foo: 1}, {bar: 2}, {baz: 3}]); //=> {foo:1,bar:2,baz:3}
R.mergeAll([{foo: 1}, {foo: 2}, {bar: 2}]); //=> {foo:2,bar:2}

// move
// 将列表中 from 索引处的元素移动到索引 to 处。
R.move(0, 2, ['a', 'b', 'c', 'd', 'e', 'f']); //=> ['b', 'c', 'a', 'd', 'e', 'f']
R.move(-1, 0, ['a', 'b', 'c', 'd', 'e', 'f']); //=> ['f', 'a', 'b', 'c', 'd', 'e'] list rotation

// none
// 如果列表中的元素都不满足 predicate,返回 true;否则返回 false。
// 若第二个参数自身存在 none 方法,则调用自身的 none 方法。
const isEven = n => n % 2 === 0;
const isOdd = n => n % 2 === 1;
R.none(isEven, [1, 3, 5, 7, 9, 11]); //=> true
R.none(isOdd, [1, 3, 5, 7, 8, 11]); //=> false

// nth
// 返回列表或字符串的第 n 个元素。如果 n 为负数,则返回索引为 length + n 的元素。
const list = ['foo', 'bar', 'baz', 'quux'];
R.nth(1, list); //=> 'bar'
R.nth(-1, list); //=> 'quux'
R.nth(-99, list); //=> undefined
R.nth(2, 'abc'); //=> 'c'
R.nth(3, 'abc'); //=> ''

// pair
// 接收两个参数,fst 和 snd,返回数组 [fst, snd]。
console.log(R.pair('foo', 'bar', 'abc')); //=> ['foo', 'bar']


// partition
// 通过 predicate 将列表或 "Filterable" (可过滤的)对象分成两部分,
// 分别为满足 predicate 的元素和不满足 predicate 的元素。元素类型保持不变。
// Filterable 类型包括 plain object 或者任何带有 filter 方法的类型,如 Array 。
R.partition(R.includes('s'), ['sss', 'ttt', 'foo', 'bars']);
// => [ [ 'sss', 'bars' ],  [ 'ttt', 'foo' ] ]
R.partition(R.includes('s'), {a: 'sss', b: 'ttt', foo: 'bars'});
// => [ { a: 'sss', foo: 'bars' }, { b: 'ttt' }  ]


// pluck
// 从列表内的每个对象元素中取出特定名称的属性,组成一个新的列表。
// pluck 可以作用于任何 functor ,包括 Array,因为它等价于 R.map(R.prop(k), f)。
var getAges = R.pluck('age');
getAges([{name: 'fred', age: 29}, {name: 'wilma', age: 27}]); //=> [29, 27]
R.pluck(0, [[1, 2], [3, 4]]);               //=> [1, 3]
R.pluck('val', {a: {val: 3}, b: {val: 5}}); //=> {a: 3, b: 5}

// prepend
// 在列表头部之前拼接一个元素。
R.prepend('fee', ['fi', 'fo', 'fum']); //=> ['fee', 'fi', 'fo', 'fum']


// range
// 返回从 from 到 to 之间的所有数的升序列表。左闭右开(包含 from,不包含 to)。
R.range(1, 5);    //=> [1, 2, 3, 4]
R.range(50, 53);  //=> [50, 51, 52]

// 左折叠操作。
// 遍历列表,相继调用二元迭代函数(参数为累积值和从数组中取出的当前元素),将本次迭代结果作为下次迭代的累积值。返回最终累积值。
// 可以用 R.reduced 提前终止遍历操作。
// reduce 的迭代函数接收两个参数 (acc, value),reduceRight 的迭代函数的参数顺序为 (value, acc)
// 注意:R.reduce 与原生 Array.prototype.reduce 方法不同,它不会跳过删除或未分配的索引项(稀疏矩阵)。更多关于原生 reduce 的行为,请参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Description
// 如果第三个参数自身有 reduce 方法,则调用自身的 reduce 方法。如果进行该步操作,则由用户自己来处理 R.reduced 短路操作,因为自身 reduce 方法的实现可能与 Ramda 中的 reduce 不同。
R.reduce(R.subtract, 0, [1, 2, 3, 4]) // => ((((0 - 1) - 2) - 3) - 4) = -10
//          -               -10
//         / \              / \
//        -   4           -6   4
//       / \              / \
//      -   3   ==>     -3   3
//     / \              / \
//    -   2           -1   2
//   / \              / \
//  0   1            0   1


// reduceBy
// 首先对列表中的每个元素调用函数 keyFn ,根据 keyFn 返回的字符串对列表元素进行分组。然后调用 reducer 函数 valueFn,对组内的元素进行折叠操作。
// 该函数相当于更通用的 groupBy 函数。
// 若在列表位置给出 transformer,则用做 transducer
const groupNames = (acc, {name}) => acc.concat(name)
const toGrade = ({score}) =>
  score < 65 ? 'F' :
    score < 70 ? 'D' :
      score < 80 ? 'C' :
        score < 90 ? 'B' : 'A';

var students = [
  {name: 'Abby', score: 83},
  {name: 'Bart', score: 62},
  {name: 'Curt', score: 88},
  {name: 'Dora', score: 92},
];

R.reduceBy(groupNames, [], toGrade, students)
//=> {"A": ["Dora"], "B": ["Abby", "Curt"], "F": ["Bart"]}

// reduced
// 返回一个封装的值,该值代表 reduce 或 transduce 操作的最终结果。
// 返回值是一个黑盒:不保证其内部结构的稳定性。
// 注意:这个优化不适用于上面未明确列出的函数。例如,现在还不支持 reduceRight。
R.reduce(
  (acc, item) => item > 3 ? R.reduced(acc) : acc.concat(item),
  [],
  [1, 2, 3, 4, 5]) // [1, 2, 3]

// reduceRight
// 右折叠操作。
// 遍历列表,相继调用二元迭代函数(参数为累积值和从数组中取出的当前元素),将本次迭代结果作为下次迭代的累积值。返回最终累积值。
// 类似于 reduce,除了遍历列表的顺序是从右向左的。
// reduceRight 的迭代函数接收两个参数 (value, acc)。与之对应的,reduce 的迭代函数的参数顺序为 (acc, value)
// 注意:R.reduceRight 与原生 Array.prototype.reduceRight 方法不同,它不会跳过删除或未分配的索引项(稀疏矩阵)。
// 更多关于原生 reduceRight 的行为,请参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight#Description
R.reduceRight(R.subtract, 0, [1, 2, 3, 4]) // => (1 - (2 - (3 - (4 - 0)))) = -2
//    -               -2
//   / \              / \
//  1   -            1   3
//     / \              / \
//    2   -     ==>    2  -1
//       / \              / \
//      3   -            3   4
//         / \              / \
//        4   0            4   0

// reduceWhile
// 与 reduce 类似, reduceWhile 会遍历列表,相继调用二元迭代函数,并返回最终累积值。
// reduceWhile 在每次调用迭代函数前,先使用 predicate 进行判断,
// 如果 predicate 返回 false ,则提前终止遍历操作,并返回当前累积值。
const isOdd2 = (acc, x) => x % 2 === 1;
const xs = [1, 3, 5, 60, 777, 800];
R.reduceWhile(isOdd2, R.add, 0, xs); //=> 9
const ys = [2, 4, 6]
R.reduceWhile(isOdd2, R.add, 111, ys); //=> 111

// reject
// filter 的补操作。返回结果为 R.filter 操作结果的补集。
// 若在列表位置给出 transformer,则用作 transducer。
// Filterable 类型包括 plain object 或者任何带有 filter 方法的类型,如 Array 。
const isOdd3 = (n) => n % 2 === 1;
R.reject(isOdd3, [1, 2, 3, 4]); //=> [2, 4]
R.reject(isOdd3, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}

// remove
// 删除列表中从 start 开始的 count 个元素。注意,该操作是非破坏性的:不改变原列表,返回处理后列表的拷贝。
R.remove(2, 3, [1, 2, 3, 4, 5, 6, 7, 8]); //=> [1,2,6,7,8]

// repeat
// 生成包含 n 个同一元素的数组。
R.repeat('hi', 5); //=> ['hi', 'hi', 'hi', 'hi', 'hi']
const obj = {};
const repeatedObjs = R.repeat(obj, 5); //=> [{}, {}, {}, {}, {}]
repeatedObjs[0] === repeatedObjs[1]; //=> true

// reverse
// 对列表或字符串的排列顺序取反。
R.reverse([1, 2, 3]);  //=> [3, 2, 1]
R.reverse([1, 2]);     //=> [2, 1]
R.reverse([1]);        //=> [1]
R.reverse([]);         //=> []
R.reverse('abc');      //=> 'cba'
R.reverse('ab');       //=> 'ba'
R.reverse('a');        //=> 'a'
R.reverse('');         //=> ''

// Scan 与 reduce 类似,但会将每次迭代计算的累积值记录下来,组成一个列表返回。
const numbers = [1, 2, 3, 4];
const factorials = R.scan(R.multiply, 1, numbers); //=> [1, 1, 2, 6, 24]

// sequence
// 将一个 Applicative 的 Traversable 转换成一个 Traversable 类型的 Applicative。
// 如果第二个参数自身存在 sequence 方法,则调用自身的 sequence。
R.sequence(Maybe.of, [Just(1), Just(2), Just(3)]);   //=> Just([1, 2, 3])
R.sequence(Maybe.of, [Just(1), Just(2), Nothing()]); //=> Nothing()

R.sequence(R.of, Just([1, 2, 3])); //=> [Just(1), Just(2), Just(3)]
R.sequence(R.of, Nothing());       //=> [Nothing()]

// slice
// 取出给定的列表或字符串(或带有 slice 方法的对象)中,从 fromIndex(包括)到 toIndex(不包括)的元素。
// 如果第三个参数自身存在 slice 方法,则调用自身的 slice 方法。
R.slice(1, 3, ['a', 'b', 'c', 'd']);        //=> ['b', 'c']
R.slice(1, Infinity, ['a', 'b', 'c', 'd']); //=> ['b', 'c', 'd']
R.slice(0, -1, ['a', 'b', 'c', 'd']);       //=> ['a', 'b', 'c']
R.slice(-3, -1, ['a', 'b', 'c', 'd']);      //=> ['b', 'c']
R.slice(0, 3, 'ramda');                     //=> 'ram'

// sort
// 使用比较函数对列表进行排序。比较函数每次接受两个参数,如果第一个值较小,则返回负数;
// 如果第一个值较大,则返回正数;如果两值相等,返回零。注意,返回的是列表的 拷贝 ,不会修改原列表。
const diff = function (a, b) {
  return a - b;
};
R.sort(diff, [4, 2, 7, 5]); //=> [2, 4, 5, 7]

// splitAt
// 在指定的索引处拆分列表或者字符串。
R.splitAt(1, [1, 2, 3]);          //=> [[1], [2, 3]]
R.splitAt(5, 'hello world');      //=> ['hello', ' world']
R.splitAt(-1, 'foobar');          //=> ['fooba', 'r']

// splitEvery
// 将列表拆分成指定长度的子列表集。
R.splitEvery(3, [1, 2, 3, 4, 5, 6, 7]); //=> [[1, 2, 3], [4, 5, 6], [7]]
R.splitEvery(3, 'foobarbaz'); //=> ['foo', 'bar', 'baz']

// splitWhen
// 查找列表中首个满足 predicate 的元素,在该处将列表拆分为两部分。首个满足 predicate 的元素包含在后一部分。
R.splitWhen(R.equals(2), [1, 2, 3, 1, 2, 3]);   //=> [[1], [2, 3, 1, 2, 3]]

// startsWith
// 检查列表是否以给定的值开头。
R.startsWith('a', 'abc')                //=> true
R.startsWith('b', 'abc')                //=> false
R.startsWith(['a'], ['a', 'b', 'c'])    //=> true
R.startsWith(['b'], ['a', 'b', 'c'])    //=> false

// tail
// 删除列表中的首个元素(或者调用对象的 tail 方法)。
// 如果第一个参数自身存在 slice 方法,则调用自身的 slice 方法。
R.tail([1, 2, 3]);  //=> [2, 3]
R.tail([1, 2]);     //=> [2]
R.tail([1]);        //=> []
R.tail([]);         //=> []
R.tail('abc');  //=> 'bc'
R.tail('ab');   //=> 'b'
R.tail('a');    //=> ''
R.tail('');     //=> ''

// take
// 返回列表的前 n 个元素、字符串的前n个字符或者用作 transducer/transform(或者调用对象的 take 方法)。
// 如果第二个参数自身存在 take 方法,则调用自身的 take 方法。
R.take(1, ['foo', 'bar', 'baz']); //=> ['foo']
R.take(2, ['foo', 'bar', 'baz']); //=> ['foo', 'bar']
R.take(3, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz']
R.take(4, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz']
R.take(3, 'ramda');               //=> 'ram'

const personnel = [
  'Dave Brubeck',
  'Paul Desmond',
  'Eugene Wright',
  'Joe Morello',
  'Gerry Mulligan',
  'Bob Bates',
  'Joe Dodge',
  'Ron Crotty'
];
const takeFive = R.take(5);
takeFive(personnel);
//=> ['Dave Brubeck', 'Paul Desmond', 'Eugene Wright', 'Joe Morello', 'Gerry Mulligan']


// takeLast
// 返回列表的后 n 个元素。如果 n > list.length,则返回 list.length 个元素。
R.takeLast(1, ['foo', 'bar', 'baz']); //=> ['baz']
R.takeLast(2, ['foo', 'bar', 'baz']); //=> ['bar', 'baz']
R.takeLast(3, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz']
R.takeLast(4, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz']
R.takeLast(3, 'ramda');               //=> 'mda'

// takeLastWhile
// 从后往前取出列表元素,直到遇到首个不满足 predicate 的元素为止。取出的元素中不包含首个不满足 predicate 的元素。
const isNotOne = x => x !== 1;
R.takeLastWhile(isNotOne, [1, 2, 3, 4]); //=> [2, 3, 4]
R.takeLastWhile(x => x !== 'R', 'Ramda'); //=> 'amda'

// takeWhile
// 从前往后取出列表元素,直到遇到首个不满足 predicate 的元素为止。取出的元素中不包含首个不满足 predicate 的元素。
// 若第二个参数自身存在 takeWhile 方法,则调用自身的 takeWhile 方法
// 若在列表位置中给出 transfomer,则用作 transducer 。
const isNotFour = x => x !== 4;
R.takeWhile(isNotFour, [1, 2, 3, 4, 3, 2, 1]); //=> [1, 2, 3]
R.takeWhile(x => x !== 'd', 'Ramda'); //=> 'Ram'

// times
// 执行输入的函数 n 次,返回由函数执行结果组成的数组。
// fn 为一元函数,n 次调用接收的参数为:从 0 递增到 n-1 。
R.times(R.identity, 5); //=> [0, 1, 2, 3, 4]


// 用 iterator function 初始化 transducer ,生成一个 transformed iterator function。然后顺次遍历列表,对每个列表元素先进行转换,然后与累积值进行归约,返回值作为下一轮迭代的累积值。最终返回与初始累积值类型相同的一个累积值。
// iterator function 接收两个参数: (acc, value) ,iterator function 会被封装为 transformer 来初始化 transducer 。可以直接传递 transformer 来代替 iterator function。这两种情况下,可以使用 R.reduced 提前终止迭代操作。
// transducer 函数接受一个 transformer ,返回一个新的 transformer ,并且 transducer 函数可以直接组合。
// transformer 是一个对象,其中包含二元 reducing iterator、step、零元 init 和 一元 result 函数。step 作为 reduce 过程中的迭代函数;result 将最终的累积值转换为需要的返回类型(通常为 R.identity );init 提供初始累积值,但通常会被 transduce 函数忽略。
// 在 transducer 初始化之后,使用 R.reduce 进行迭代操作。
const numbers3 = [1, 2, 3, 4];
const transducer = R.compose(R.map(R.add(1)), R.take(2));
R.transduce(transducer, R.flip(R.append), [], numbers3); //=> [2, 3]
const isOdd4 = (x) => x % 2 === 1;
const firstOddTransducer = R.compose(R.filter(isOdd4), R.take(1));
R.transduce(firstOddTransducer, R.flip(R.append), [], R.range(0, 100)); //=> [1]


// transpose
// 二维数组行列转置。输入 n 个长度为 x 的数组,输出 x 个长度为 n 的数组。
R.transpose([[1, 'a'], [2, 'b'], [3, 'c']]) //=> [[1, 2, 3], ['a', 'b', 'c']]
R.transpose([[1, 2, 3], ['a', 'b', 'c']]) //=> [[1, 'a'], [2, 'b'], [3, 'c']]
// If some of the rows are shorter than the following rows, their elements are skipped:
R.transpose([[10, 11], [20], [], [30, 31, 32]]) //=> [[10, 20, 30], [11, 31], [32]]

// traverse
// 将返回值为 Applicative 类型的函数映射到一个 Traversable 上。然后使用 sequence 将结果由 Traversable of Applicative 转换为 Applicative of Traversable。
// 若第三个参数自身存在 traverse 方法,则调用自身的 traverse 方法。
// Returns `Maybe.Nothing` if the given divisor is `0`
const safeDiv = n => d => d === 0 ? Maybe.Nothing() : Maybe.Just(n / d)
R.traverse(Maybe.of, safeDiv(10), [2, 4, 5]); //=> Maybe.Just([5, 2.5, 2])
R.traverse(Maybe.of, safeDiv(10), [2, 0, 5]); //=> Maybe.Nothing

// unfold
// 通过一个种子值( seed )创建一个列表。unfold 接受一个迭代函数:
// 该函数或者返回 false 停止迭代,或者返回一个长度为 2 的数组:
// 数组首个元素添加到结果列表,第二个元素作为种子值传给下一轮迭代使用。
// 迭代函数接受单个参数: (seed)。
const f = n => n > 50 ? false : [-n, n + 10];
R.unfold(f, 10); //=> [-10, -20, -30, -40, -50]

// uniq
// 列表去重操作。返回无重复元素的列表。通过 R.equals 函数进行相等性判断。
R.uniq([1, 1, 2, 1]); //=> [1, 2]
R.uniq([1, '1']);     //=> [1, '1']
R.uniq([[42], [42]]); //=> [[42]]

// uniqBy
// 返回无重复元素的列表。元素通过给定的函数的返回值以及 R.equals 进行相同性判断。如果给定的函数返回值相同,保留第一个元素。
R.uniqBy(Math.abs, [-1, -5, 2, 10, 1, 2]); //=> [-1, -5, 2, 10]

// uniqWith
// 返回无重复元素的列表。元素通过 predicate 进行相同性判断。如果通过 predicate 判断两元素相同,保留第一个元素。
const strEq = R.eqBy(String);
R.uniqWith(strEq)([1, '1', 2, 1]); //=> [1, 2]
R.uniqWith(strEq)([{}, {}]);       //=> [{}]
R.uniqWith(strEq)([1, '1', 1]);    //=> [1]
R.uniqWith(strEq)(['1', 1, 1]);    //=> ['1']

// unnest
// R.chain(R.identity) 的简写, 对 Chain 类型的数据消除一层嵌套.
R.unnest([1, [2], [[3]]]); //=> [1, 2, [3]]
R.unnest([[1, 2], [3, 4], [5, 6]]); //=> [1, 2, 3, 4, 5, 6]

// update
// 替换数组中指定索引处的值。
R.update(1, '_', ['a', 'b', 'c']);      //=> ['a', '_', 'c']
R.update(-1, '_', ['a', 'b', 'c']);     //=> ['a', 'b', '_']

// without
// 求第二个列表中,未包含在第一个列表中的任一元素的集合。通过 R.equals 函数进行相等性判断。
// 若在列表位置中给出 transfomer,则用作 transducer 。
R.without([1, 2], [1, 2, 1, 3, 4]); //=> [3, 4]

// xprod
//将两个列表的元素两两组合,生成一个新的元素对列表。
R.xprod([1, 2], ['a', 'b']); //=> [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]

// zip
// 将两个列表对应位置的元素组合,生成一个新的元素对列表。生成的列表长度取决于较短的输入列表的长度。
// 注意,zip 等价于 zipWith(function(a, b) { return [a, b] }) 。
R.zip([1, 2, 3], ['a', 'b', 'c']); //=> [[1, 'a'], [2, 'b'], [3, 'c']]


// zipObj
// 将两个列表对应位置的元素作为键值对组合,生成一个新的键值对的列表。生成的列表长度取决于较短的输入列表的长度。
// 注意,zipObj 等价于 pipe(zip, fromPairs) 。
R.zipObj(['a', 'b', 'c'], [1, 2, 3]); //=> {a: 1, b: 2, c: 3}

// zipWith
// 将两个列表对应位置的元素通过一个函数处理,生成一个新的元素的列表。生成的列表长度取决于较短的输入列表的长度。
const ff = (x, y) => {
  // ...
};
R.zipWith(ff, [1, 2, 3], ['a', 'b', 'c']);
//=> [ff(1, 'a'), ff(2, 'b'), ff(3, 'c')]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值