LoginSignup
42
42

More than 5 years have passed since last update.

lodash自分用メモ Collection

Posted at

lodashは見ておこうと思い立ち、サイトの日本語メモを作成しました。

↓ lodashのES6で書くとこうなるというのはこちらのサイト

You Might Not Need Lodash

_.countBy(collection, [iteratee=_.identity])

配列から、[iteratee=_.identity]で渡した条件の結果をkey、条件に当てはまる値の数をvalueに返す。

公式)Creates an object composed of keys generated from the results of running each element of collection thru iteratee. The corresponding value of each key is the number of times the key was returned by iteratee. The iteratee is invoked with one argument: (value).

let array = [
  { username: 'John', score: 36 },
  { username: 'Jake', score: 50 },
  { username: 'Bill', score: 20 }
]

let object = _.countBy(array, function(rec) {
  return rec.score >= 50
})

// 条件の結果がfalseだったのが2つ、trueが1つ
object // {"false":2,"true":1}
console.log(object.false); // 2
console.log(object.true); // 1

各要素の文字列の長さを素早く取得したい

_.countBy(['foo', 'man', 'chew','happy','bar'], 'length')
// {"3":3,"4":1,"5":1}

_.every(collection, [predicate=_.identity])

全ての値が評価条件をクリアした場合のみtureを返し、一つでも合致していないとfalseを返す。

公式)Checks if predicate returns truthy for all elements of collection. Iteration is stopped once predicate returns falsey. The predicate is invoked with three arguments: (value, index|key, collection).

let array = [
  { username: 'John', score: 36 },
  { username: 'Jake', score: 50 },
  { username: 'Bill', score: 20 }
]

_.every(array, function(item) {
  return item.score > 0
})
// true

_.every(array, function(item) {
  return item.score > 20
})
// false

_.filter(collection, [predicate=_.identity])

配列から条件に合致する値を配列で返す。

公式)Iterates over elements of collection, returning an array of all elements predicate returns truthy for. The predicate is invoked with three arguments: (value, index|key, collection).

let events = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 === 0 })
events // [2,4,6]
let array = [
  { username: 'John', score: 36, active: true },
  { username: 'Jake', score: 50, active: true },
  { username: 'Bill', score: 20, active: false }
]

_.filter(array, 'active')
// [{"username":"John","score":36,"active":true},{"username":"Jake","score":50,"active":true}]

_.filter(array, { score: 20 })
// [{"username":"Bill","score":20,"active":false}]

_.find(collection, [predicate=_.identity], [fromIndex=0])

ES6のfindと同じ。要素から条件に合致する、最初の値を返す。

公式)Iterates over elements of collection, returning the first element predicate returns truthy for. The predicate is invoked with three arguments: (value, index|key, collection).

let array = [
  { username: 'John', score: 36, active: true },
  { username: 'Jake', score: 50, active: true },
  { username: 'Bill', score: 20, active: false }
]

_.find(array, function(item) {
  return item.score > 20
})
// {"username":"John","score":36,"active":true}

_.find(array, ['active', true])
// {"username":"John","score":36,"active":true}

_.findLast(collection, [predicate=_.identity], [fromIndex=collection.length-1])

使い方は_.findと同じ。要素の右から探して最初に合致する値を返す。

公式)This method is like _.find except that it iterates over elements of collection from right to left.

let array = [
  { username: 'John', score: 36, active: true },
  { username: 'Jake', score: 50, active: true },
  { username: 'Bill', score: 20, active: false }
]

_.findLast(array, ['active', true])
// {"username":"Jake","score":50,"active":true}

_.flatMap(collection, [iteratee=_.identity])

配列の要素に渡した関数を適用した後の結果を展開し、最終結果は連結してフラットになって返ってくる。

公式)Creates a flattened array of values by running each element in collection thru iteratee and flattening the mapped results. The iteratee is invoked with three arguments: (value, index|key, collection).

function duplicate(n) {
  return [n, n]
}
_.flatMap([1, 2], duplicate) // => [1, 1, 2, 2]

const map = value => [value + 1, value -1]
_.flatMap([1, 2, 3], map) // => [2,0,3,1,4,2]

_.flatMapDeep(collection, [iteratee=_.identity])

_.flatMapと使い方は一緒だが、返ってくる値は完全に階層を持たない、フラットな配列になる。

公式)This method is like _.flatMap except that it recursively flattens the mapped results.

const map = value => [[value + 1], [value -1]]
_.flatMap([1, 2, 3], map) // => [[2],[0],[3],[1],[4],[2]]

_.flatMapDeep([1, 2, 3], map) // => [2,0,3,1,4,2]

_.flatMapDepth(collection, [iteratee=_.identity], [depth=1])

_.flatMapDeepと使い方は似ているが、指定された回数だけ結果がフラットされる点が違う。depthのデフォルト値は1なので、何も指定しなければ_.flatMapと同じになる。

公式)This method is like _.flatMap except that it recursively flattens the mapped results up to depth times.

const duplicate = value => [[[value, value]]];
_.flatMapDepth([1, 2, 3], duplicate, 2)
// [[1,1],[2,2],[3,3]]

_.forEach(collection, [iteratee=_.identity])

ES6のforEachと同じ。[iteratee=_.identity]で指定した関数をループして処理する。return falsebreak

公式)Iterates over elements of collection and invokes iteratee for each element. The iteratee is invoked with three arguments: (value, index|key, collection). Iteratee functions may exit iteration early by explicitly returning false.

_.forEach([1, 2], function(value) {
  console.log(value) // `1` → `2` の順に表示
})

_.forEachRight(collection, [iteratee=_.identity])

使い方は_.forEachと同じだが、配列の右から処理が掛けられて返ってくる。

公式)This method is like _.forEach except that it iterates over elements of collection from right to left.

_.forEachRight([1, 2], function(value) {
  console.log(value) // `2` → `1` の順に表示
})

_.groupBy(collection, [iteratee=_.identity])

配列から、繰り返し実行された処理の結果を、結果をkey、該当する値を配列にして返す。

公式)Creates an object composed of keys generated from the results of running each element of collection thru iteratee. The order of grouped values is determined by the order they occur in collection. The corresponding value of each key is an array of elements responsible for generating the key. The iteratee is invoked with one argument: (value).

const charaArray = [{
    id: 25,
    name: 'ピカチュウ',
    type: [ 'でんき' ]
},{
    id: 35,
    name: 'ピッピ',
    type: [ 'ノーマル' ]
},{
    id: 39,
    name: 'プリン',
    type: [ 'ノーマル' ]
}]

_.mapKeys(charaArray, 'id')
// {
//   "25": {
//     "id":25,
//     "name":"ピカチュウ",
//     "type":["でんき"]
//   },
//   "35": {
//     "id":35,
//     "name":"ピッピ",
//     "type":["ノーマル"]
//   },
//   "39": {
//     "id":39,
//     "name":"プリン",
//     "type":["ノーマル"]
//   }
// }
let nums = [2, 20, 4, 3, 7, 8, 32, 42, 256]

const grouped = _.groupBy(nums, function(n){
  return n < 10 ? 'fail' : 'pass'
})

grouped
// {"fail":[2,4,3,7,8],"pass":[20,32,42,256]}
let clases = [
    {name: '算数', grade: 83},
    {name: '国語', grade: 100},
    {name: '理科', grade: 98}, 
    {name: '社会科', grade: 93},
    {name: '英語', grade: 42},
    {name: '体育', grade: 60}
];

let gradeClases = function (clases) {
  let letters = {
        'A+': 98,
        'A.': 93,
        'A-': 90,
        'B+': 86,
        'B.': 83,
        'B-': 80,
        'C+': 76,
        'C.': 73,
        'C-': 70,
        'D+': 66,
        'D.': 63,
        'D-': 60
    };

  return _.groupBy(clases, function(sub){
    let key = 'F.'

    _.forEach(letters, function(g, letter) {
      if (sub.grade >= g ) {
        key = letter
        return false
      }
    })
    return key
  })
}

gradeClases(clases)
// {
//   "B.":[
//     {"name":"算数","grade":83}
//   ],
//   "A+":[
//     {"name":"国語","grade":100},
//     {"name":"理科","grade":98}
//   ],
//   "A.":[
//     {"name":"社会科","grade":93}
//   ],
//   "F.":[
//     {"name":"英語","grade":42}
//   ],
//   "D-":[
//     {"name":"体育","grade":60}
//   ]
// }

_.includes(collection, value, [fromIndex=0])

指定した値がコレクション内にあるかチェックし、あればtrue、なければfalseを返す。コレクションが文字列だった場合、引数で渡した文字列に1文字でも合致していればtrueを返す。

公式)Checks if value is in collection. If collection is a string, it's checked for a substring of value, otherwise SameValueZero is used for equality comparisons. If fromIndex is negative, it's used as the offset from the end of collection.

// 文字列から探す
let str = 'ピカチュウ, イーブイ, ポケモン';
_.includes(str, 'カビゴン') // true
_.includes(str, 'ピカチュウ') // false

// 配列から探す
let array = ['a','b','c'];
_.includes(array,42) // false
_.includes(array,'d') // false
_.includes(array,'c') // true

// オブジェクトから探す
let object = { name: 'レッド', level: 32 }
_.includes(object, 'name') // false
_.includes(object, 'グリーン') // false
_.includes(object, 'レッド') // true

_.invokeMap(collection, path, [args])

引数で指定したものを関数として、実行した結果を配列にして返す。追加の引数も指定できる。

公式)Invokes the method at path of each element in collection, returning an array of the results of each invoked method. Any additional arguments are provided to each invoked method. If path is a function, it's invoked for, and this bound to, each element in collection.

_.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); // => [[1, 5, 7], [1, 2, 3]]

_.invokeMap([123, 456], String.prototype.split, ''); // => [['1', '2', '3'], ['4', '5', '6']]

_.invokeMap(['a', 'b', 'c'], 'toUpperCase') // => ["A","B","C"]

_.invokeMap([['a', 'b'], ['c', 'd']], 'join', '') // => ["ab","cd"]

_.invokeMap([{ a: 1}, { a: 2 }], function(toAdd) {
  return this.a + toAdd
}, 3)
// [4,5]

_.keyBy(collection, [iteratee=_.identity])

指定した[iteratee=.identity](値または関数)を実行して、結果をkeyとしたオブジェクトを生成する。
使い方は`
.groupBy`と似ているが、最後の要素だけ返すところが違う。

公式)Creates an object composed of keys generated from the results of running each element of collection thru iteratee. The corresponding value of each key is the last element responsible for generating the key. The iteratee is invoked with one argument: (value).

const charaArray = [{
    id: 25,
    name: 'ピカチュウ',
    type: [ 'でんき' ]
},{
    id: 35,
    name: 'ピッピ',
    type: [ 'ノーマル' ]
},{
    id: 39,
    name: 'プリン',
    type: [ 'ノーマル' ]
}]

// 実行結果は`_.groupBy`と変わらない
_.keyBy(charaArray, 'id')
// {
//   "25":{
//     "id":25,
//     "name":"ピカチュウ",
//     "type":["でんき"]
//   },
//   "35":{
//     "id":35,
//     "name":"ピッピ",
//     "type":["ノーマル"]
//   },
//   "39":{
//     "id":39,
//     "name":"プリン",
//     "type":["ノーマル"]
//   }
// }
_.keyBy([1, 2, 3], n => n > 1)
// => {"false":1,"true":3}
_.groupBy([1, 2, 3], n => n > 1)
// => {"false":[1],"true":[2,3]}


_.keyBy({ a: 10, b: 20, c: 20 }, val => val / 2 )
// => {"5":10,"10":20}

_.map(collection, [iteratee=_.identity])

[iteratee=_.identity]で渡した値・関数などを繰り返し実行した結果を返す。

公式)Creates an array of values by running each element in collection thru iteratee. The iteratee is invoked with three arguments:
(value, index|key, collection).
Many lodash methods are guarded to work as iteratees for methods like _.every, _.filter, _.map, _.mapValues, _.reject, and _.some.

The guarded methods are:

ary, chunk, curry, curryRight, drop, dropRight, every, fill, invert, parseInt, random, range, rangeRight, repeat, sampleSize, slice, some, sortBy, split, take, takeRight, template, trim, trimEnd, trimStart, and words
_.map([1, 2, 3], n => n * 2 ) // => [2,4,6]

const users = [
  { name: 'Alex' },
  { name: 'Bob'}
]

_.map(users, 'name') // => ["Alex","Bob"]
_.map(users, { name: 'Alex' }) // => [true,false]

_.orderBy(collection, [iteratees=[_.identity]], [orders])

_.sortByと使い方は一緒だが、ソート順を昇順・降順決められるところが違う。引数でascdescを指定してあげる。

公式)This method is like _.sortBy except that it allows specifying the sort orders of the iteratees to sort by. If orders is unspecified, all values are sorted in ascending order. Otherwise, specify an order of "desc" for descending or "asc" for ascending sort order of corresponding values.

var users = [
  { 'user': 'fred',   'age': 48 },
  { 'user': 'barney', 'age': 36 },
  { 'user': 'fred',   'age': 40 },
  { 'user': 'barney', 'age': 34 }
];

_.sortBy(users, ['user', 'age']);
// [{"user":"barney","age":34},{"user":"barney","age":36},{"user":"fred","age":40},{"user":"fred","age":48}]
_.orderBy(users, ['user', 'age'], ['asc', 'desc']);
// [{"user":"barney","age":36},{"user":"barney","age":34},{"user":"fred","age":48},{"user":"fred","age":40}]
let array = [
  { "id":1, "name":"C" },
  { "id":2, "name":"F" },
  { "id":3, "name":"B" },
  { "id":4, "name":"A" },
  { "id":5, "name":"E" },
  { "id":6, "name":"D" }
]
_.orderBy(array, ['name'], ['asc'])
// => [{"id":4,"name":"A"},{"id":3,"name":"B"},{"id":1,"name":"C"},{"id":6,"name":"D"},{"id":5,"name":"E"},{"id":2,"name":"F"}]

_.partition(collection, [predicate=_.identity])

渡した条件によって配列を2つのグループに分ける関数。
1つ目の配列にはtrueの値、2つ目はfalseの値を返す。条件に一致するものとしないものに分別された結果が配列に返ってくる。

公式)Creates an array of elements split into two groups, the first of which contains elements predicate returns truthy for, the second of which contains elements predicate returns falsey for. The predicate is invoked with one argument: (value).

const users = [
  { id: 1, name: 'Alice',   age: 20 },
  { id: 2, name: 'Bob',     age: 15 },
  { id: 3, name: 'Charlie', age: 10 },
];

_.partition( users, user => user.age < 20 )

// [
//   [
//     {"id":2,"name":"Bob","age":15},
//     {"id":3,"name":"Charlie","age":10}
//   ],
//   [
//     {"id":1,"name":"Alice","age":20}
//   ]
// ]

_.reduce(collection, [iteratee=_.identity], [accumulator])

配列またはオブジェクトの左から処理を実行していく。その時、累積した値と処理が実行されるため、単一の値に減らして返す。第三引数の[accumulator]の戻り値の形式を自由に選択できるので、[accumulator]には数値やboolean等も使える。
(ES6のreduceと一緒だが、lodashの方が少し堅牢なのだそう。)

公式)Reduces collection to a value which is the accumulated result of running each element in collection thru iteratee, where each successive invocation is supplied the return value of the previous. If accumulator is not given, the first element of collection is used as the initial value. The iteratee is invoked with four arguments:
(accumulator, value, index|key, collection).
Many lodash methods are guarded to work as iteratees for methods like _.reduce, _.reduceRight, and _.transform.
The guarded methods are:
assign, defaults, defaultsDeep, includes, merge, orderBy, and sortBy

// 関数が3回呼び出されている
let sum = _.reduce([1, 1, 1, 1], function(acc, cur) {
    return acc + cur
})
sum // 4
let array = [1, 2, 3, 4]
let sum = _.reduce(array, (acc, n) => {
    return acc + n
})
sum // 10
let users = [
  { name: 'John', age: 30 },
  { name: 'Jane', age: 29 },
  { name: 'Bill', age: 65 },
  { name: 'Emily', age: 17 },
  { name: 'Jack', age: 30 }
]

let reducedUsers = _.reduce(users, function(result, user) {
  if (user.age >= 18 && user.age <= 59) {
    (result[user.age] || (result[user.age] = [])).push(user)
  }
  return result
}, {})

reducedUsers
// {"29":[{"name":"Jane","age":29}],"30":[{"name":"John","age":30},{"name":"Jack","age":30}]}

_.reduceRight(collection, [iteratee=_.identity], [accumulator])

_.reduceと使い方は同じだが、処理する順番が右から左。

公式)his method is like _.reduce except that it iterates over elements of collection from right to left.

let array = [[0, 1], [2, 3], [4, 5]]

_.reduceRight(array, function(flattened, other) {
  return flattened.concat(other)
}, [])
// [4, 5, 2, 3, 0, 1]

_.reject(collection, [predicate=_.identity])

配列またはオブジェクトから、指定した条件に合致する値以外を返す。_.filterと返ってくる値が逆。

公式)The opposite of _.filter; this method returns the elements of collection that predicate does not return truthy for.

let users = [
  { 'user': 'barney', 'age': 36, 'active': false },
  { 'user': 'fred',   'age': 40, 'active': true }
]

_.reject(users, { 'age': 40, 'active': true })
// [{"user":"barney","age":36,"active":false}]
_.filter(users, { 'age': 40, 'active': true })
// [{"user":"fred","age":40,"active":true}]
_.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; })
// [1, 3, 5]

_.sample(collection)

コレクションからランダムな要素を取得する。

公式)Gets a random element from collection.

_.sample([1, 2, 3, 4]) // 2(ランダムな数字1つ返ってくる)

_.sampleSize(collection, [n=1])

_.sampleはランダムな値1つだけ返ってくるが、これは取得できる個数を引数で指定できる。

公式)Gets n random elements at unique keys from collection up to the size of collection.

_.sampleSize([1, 2, 3], 2) // [3, 1] (ランダムな数字2つ)

_.sampleSize([1, 2, 3], 4) // [2, 3, 1]

_.shuffle(collection)

渡した配列をシャッフルしてくれる。

公式)Creates an array of shuffled values, using a version of the Fisher-Yates shuffle.

_.shuffle([1, 2, 3, 4]) // [4, 1, 3, 2]
let users = [
  { name: 'John', age: 30 },
  { name: 'Jane', age: 29 },
  { name: 'Bill', age: 65 },
  { name: 'Emily', age: 17 },
  { name: 'Jack', age: 30 }
]

users = _.shuffle(users);
// [
//   {"name":"Bill","age":65},
//   {"name":"Jack","age":30},
//   {"name":"Jane","age":29},
//   {"name":"Emily","age":17},
//   {"name":"John","age":30}
// ]

_.size(collection)

値の長さやプロパティの数など、lengthを返してくれる。
配列はlength、Stringは文字数。

公式)Gets the size of collection by returning its length for array-like values or the number of own enumerable string keyed properties for objects.

_.size([1, 2, 3, 4, 5]) // 5

_.size({ 'one': 1, 'two': 2, 'three': 3 }) // 3

_.size('ピカチュウ') // 5

_.some(collection, [predicate=_.identity])

コレクションが渡した条件を一つでも満たしていればtrueを返す。
_.everyは使い方は_.someに近いが、全ての条件を満たさないとtrueを返さない。

公式)Checks if predicate returns truthy for any element of collection. Iteration is stopped once predicate returns truthy. The predicate is invoked with three arguments: (value, index|key, collection).

_.some([3,2,9,6], elem => (elem % 2) == 1) // true
let pokemons = [
  { id: 1, name: 'Bulbizarre' },
  { id: 2, name: 'Herbizarre' },
  { id: 3, name: 'Florizarre' }
];
_.some(pokemons, { id: 1 }) // true
_.some(pokemons, { id: 4 }) // false

_.sortBy(collection, [iteratees=[_.identity]])

コレクション内の各要素で処理が実行された結果を昇順にソートして返す。

公式)Creates an array of elements, sorted in ascending order by the results of running each element in a collection thru each iteratee. This method performs a stable sort, that is, it preserves the original sort order of equal elements. The iteratees are invoked with one argument: (value).

let nums = [5, 42, -5, 7, 6, 3, 52, 27, 158, -1];
_.sortBy(nums)
// [ -5, -1, 3, 5, 6, 7, 27, 42, 52, 158 ]
let users = [
  { name: 'John', age: 30 },
  { name: 'Jane', age: 29 },
  { name: 'Bill', age: 65 },
  { name: 'Emily', age: 17 },
  { name: 'Jack', age: 30 }
]

_.sortBy(users, 'age')
// [
//   {"name":"Emily","age":17},
//   {"name":"Jane","age":29},
//   {"name":"John","age":30},
//   {"name":"Jack","age":30},
//   {"name":"Bill","age":65}
// ]
let pokemons = [
  { name: 'ピカチュウ', lv: 85 },
  { name: 'カビゴン', lv: 40 },
  { name: 'ポッポ', lv: 20 },
  { name: 'フシギバナ', lv: 10 },
  { name: 'ラッタ', lv: 60 }
]

_.sortBy(pokemons, item => {
  return item.name.length
})
// [
//   {"name":"ポッポ","lv":20},
//   {"name":"ラッタ","lv":60},
//   {"name":"カビゴン","lv":40},
//   {"name":"ピカチュウ","lv":85},
//   {"name":"フシギバナ","lv":10}
// ]

やっとlodashのCollectionが終わった…!😭
lodashはまだまだ続くので、多分次は別記事を書いてモチベを上げます。

42
42
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
42