JavaScript30秒, 从入门到放弃之Array(七)

GitHub地点:
JavaScript30秒, 从入门到放弃之Array(七)

博客地点:JavaScript30秒, 从入门到放弃之Array(七)

程度有限,迎接批评指正

without

Filters out the elements of an array, that have one of the specified values.

Use Array.filter() to create an array excluding(using !Array.includes()) all given values.

const without = (arr, ...args) => arr.filter(v => !args.includes(v));

剔撤除数组中一切存在于所指定的元素们的项。

运用Array.filter()建立一个将一切供应的值消除在外(运用!Array.includes())的数组。

➜  code cat without.js
const without = (arr, ...args) => arr.filter(v => !args.includes(v));

console.log(without([2, 1, 2, 3], 1, 2));
➜  code node without.js
[ 3 ]

filterincludes连系,把数组arr中一切存在于指定的元素值…args中的项消除在外,很清新清洁。

xProd

Creates a new array out of the two supplied by creating each possible pair from the arrays.

Use Array.reduce(), Array.map() and Array.concat() to produce every possible pair from the elements of the two arrays and save them in an array.

const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);

建立一个新数组,数组元素由两个数组的元素交织组合而成。

运用Array.reduce()Array.map()Array.concat()来建立由两个数组元素拼接而成的一切可能对并将它们存在一个数组中的数组。

➜  code cat xProd.js
const xProd = (a, b) => a.reduce((acc, val) => acc.concat(b.map(v => [val, v])), []);

console.log(xProd([1, 2], ['a', 'b']));

➜  code node xProd.js
[ [ 1, 'a' ], [ 1, 'b' ], [ 2, 'a' ], [ 2, 'b' ] ]

reduce初始值acc是一个空数组[],跟着遍历的举行accconcat天生的元素组合对的数组。组合对就是由b.map(v => [val, v]天生的。也就是reduce遍历一次时,数组a的一个元素离别和数组b的一切元素离别组成一对。

zip

Creates an array of elements, grouped based on the position in the original arrays.

Use Math.max.apply() to get the longest array in the arguments. Creates an array with that length as return value and use Array.from()with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary, undefined is used where no value could be found.

const zip = (...arrays) => {
  const maxLength = Math.max(...arrays.map(x => x.length));
  return Array.from({ length: maxLength }).map((_, i) => {
    return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
  });
};

建立一个数组,数组元素由指定的多个数组依据位置对应分组而成的数组组成。比方,多个数组的第一个元素组成一个新数组,第二个元素组成一个新数组,顺次类推。终究把一切分类号的数组存到一个数组中。

先运用Math.max.apply()来计算出终究成组的长度,然后运用该长度连系Array.from()map去遍历建立该数组的一切分组子数组。假如个中恣意一个数组在对应位置上元素不存在(如长度为2的数组试图猎取第3个元素)则undefined将被运用。

➜  code cat zip.js
const zip = (...arrays) => {
  const maxLength = Math.max(...arrays.map(x => x.length));

  return Array.from({
    length: maxLength
  }).map((_, i) => Array.from({
      length: arrays.length
    }, (_, k) => arrays[k][i]));
};

console.log(zip(['a', 'b'], [1, 2], [true, false]));
console.log(zip(['a'], [1, 2], [true, false]));

➜  code node zip.js
[ [ 'a', 1, true ], [ 'b', 2, false ] ]
[ [ 'a', 1, true ], [ undefined, 2, false ] ]
const maxLength = Math.max(...arrays.map(x => x.length));

这是终究分红maxLength组,比方一个数组含有100个元素,另一个数组含有1个元素,终究要分红100组,所以须要用Math.max()去猎取一切数组中长度最长的谁人。

return Array.from({
    length: maxLength
  }).map((_, i) => Array.from({
    length: arrays.length
  }).map((_, k) => arrays[k][i])
);

运用Array.from连系length天生长度为maxLength的数组这没啥说的了,重点是map后的要领,map的每个数组里包括多少个元素才能够呢?轻微想一下就晓得,应该是arrays的个数,因为每个数组都要拿一个出来组装。所以这里又用了一个Array.from配上length: arrays.length来定一个数组里包括的元素数目。那末这些元素由什么组成呢?这里照样要合营一个(_, k) => arrays[k][i])要领去取arrays的元素。猎取的是对应每个数组的第i个元素。

zipObject

Given an array of valid property identifiers and an array of values, return an object associating the properties to the values.

Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using Array.reduce().

const zipObject = (props, values) =>
  props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});

供应一个有用的属性标识符的数组和一个含值数组,返回一个把属性和值拼合的对象。即有用的属性标识符数组的第一项为键,含值数组的第一项为值,顺次类推。

因为一个对象值能够为undefined而键不能为undefined,所以只要有用的属性标识符数组能用来决议了对象的组成构造。因而运用Array.reduce()对该数组举行相干操纵。

➜  code cat zipObject.js
const zipObject = (props, values) => props.reduce((acc, val, i) => ((acc[val] = values[i]), acc), {});

console.log(zipObject(['a', 'b', 'c'], [1, 2]));
console.log(zipObject(['a', 'b'], [1, 2, 3]));

➜  code node zipObject.js
{ a: 1, b: 2, c: undefined }
{ a: 1, b: 2 }
(obj[prop] = values[index]), obj)

JavaScript的逗号运算符是指根据递次实行表达式,终究返回末了一个表达式的运转效果。关于这个例子来讲,就是先制造一个键值对,末了返回该对象。换平常的写法就是以下:

obj[prop] = values[index];
return obj;

这点弄通了就好理解了。

实际上就是以props数组为基准,对其运用reduce要领去遍历数组,初始值obj是一个空对象{},遍历历程以props数组的值prop为键,props数组当前索引index为索引去取values数组的项为值组装成对象并返回。

因为对象的键不能为undefined,因而,假如数组props的长度比数组values小,那末values多出来的那些项就不管了。假如相反,那末该对象响应键的值为undefined

zipWith

Creates an array of elements, grouped based on the position in the original arrays and using function as the last value to specify how grouped values should be combined.

Check if the last argument provided in a function. Use Math.max() to get the longest array in the arguments. Creates an array with that length as return value and use Array.from() with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary, undefined is used where no value could be found. The function is invoked with the elements of each group (...group).

const zipWith = (...arrays) => {
 const length = arrays.length;
 let fn = length > 1 ? arrays[length - 1] : undefined;
 fn = typeof fn == 'function' ? (arrays.pop(), fn) : undefined;
 const maxLength = Math.max(...arrays.map(x => x.length));
 const result = Array.from({ length: maxLength }).map((_, i) => {
   return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
 });
 return fn ? result.map(arr => fn(...arr)) : result;
};

建立一个数组,数组元素由指定的多个数组依据位置对应分组而成的数组组成,然后分组后的数组元素运用指定要领举行连系。

➜  code cat zipWith.js
const zipWith = (...arrays) => {
  const length = arrays.length;
  let fn = length > 1 ? arrays[length - 1] : undefined;
  fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined;
  const maxLength = Math.max(...arrays.map(x => x.length));
  const result = Array.from({length: maxLength}).map((_, i) => {return Array.from({length: arrays.length}, (_, k) => arrays[k][i]);});
  return fn ? result.map(arr => fn(...arr)) : result;
};

console.log(zipWith([1, 2], [10, 20], [100, 200], (a, b, c) => a + b + c));
console.log(zipWith(
  [1, 2, 3],
  [10, 20],
  [100, 200],
  (a, b, c) => (a != null ? a : 'a') + (b != null ? b : 'b') + (c != null ? c : 'c')
));

➜  code node zipWith.js
[ 111, 222 ]
[ 111, 222, '3bc' ]
const length = arrays.length;
let fn = length > 1 ? arrays[length - 1] : undefined;
fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined;

起首这里把参数长度arrays.length存到length里,然后依据参数长度length推断参数里是不是指定了某个要领。假如length小于即是1,则没有传入指定要领,因而fn = undefined;不然,以为参数的末了一个arrays[length - 1]传入了要领。

接下来还得推断fn是不是是一个function,假如是,arrays.pop()把要领剔除,只留数组,然后返回fn赋值给fn;不然把undefined赋值给fn

实在我以为这里和前面的写反复了,我以为fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined改成下面更好:

if (typeof fn === 'function') {
  arrays.pop();
}

如许就避免了fn的反复赋值了。因为fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined这一行的作用就是为了把要领pop出去罢了,没必要再从新赋值。

const maxLength = Math.max(...arrays.map(x => x.length));

这一行计算出终究返回数组的长度,这点易证,不睁开。

const result = Array.from({ length: maxLength }).map((_, i) => {
  return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
});

这里实在和前面的zip要领是一样的,到现在为止返回的result是和zip的效果是一样的。

return fn ? result.map(arr => fn(...arr)) : result;

然后推断fn是不是是非undefined,假如是不必处置惩罚直接返回result,不然对result数组一切元素挪用fn要领并返回效果。须要注重的是参数…arr是须要睁开的,参数不是单个的数组元素,而是数组的一切元素。

到目前为止,我已把数组的都过了一遍了,不过因为这个 30 seconds of code一直在开辟当中,所以在我翻译历程当中,数组的项又增加了很多个,下面部分为新增的项。

all

Returns true if all elements in a collection are truthy, false otherwise.

Use Array.every(Boolean) to test if all elements in the collection are truthy.

const all = arr => arr.every(Boolean);

假如数组一切元素为真,返回true,不然返回false

运用 Array.every(Boolean) 来检测数组一切元素是不是都为真。

➜  code cat all.js
const all = arr => arr.every(Boolean);

console.log(all([1, 2, 3]));

➜  code node all.js
true

这实在就是Array.every()函数能做的事变。参数为Boolean就是推断是不是是数组一切元素布尔为都为真。

allBy

Returns true if the provided predicate function returns true for all elements in a collection, false otherwise.

Use Array.every() to test if all elements in the collection return true based on fn.

const allBy = (arr, fn) => arr.every(fn);

假如数组一切元素运用了指定的断言要领都为真,那末返回true,不然返回false

运用Array.every()连系fn来检测数组一切元素挪用fn后布尔值是不是都为真。

➜  code cat allBy.js
const allBy = (arr, fn) => arr.every(fn);

console.log(allBy([4, 2, 3], x => x > 1));

➜  code node allBy.js
true

all多了一个fn要领罢了,只须要把every的参数换成fn就行,这没啥可说的。

any

Returns true if at least one element in a collection is truthy, false otherwise.

Use Array.some(Boolean) to test if any elements in the collection are truthy.

const any = arr => arr.some(Boolean);

假如一个数组中至少有一个元素布尔值为真,返回true,不然返回false

运用Array.some(Boolean)来检测数组中是不是有一个元素布尔值为真。

➜  code cat any.js
const any = arr => arr.some(Boolean);

console.log(any([0, 0, 1, 0]));

➜  code node any.js
true

这就是Array.some()能够做的事变,没啥可说。

anyBy

Returns true if the provided predicate function returns true for at least one element in a collection, false otherwise.

Use Array.some() to test if any elements in the collection return true based on fn.

const anyBy = (arr, fn) => arr.some(fn);

假如对一个数组的元素运用指定的断言要领后至少有一个效果布尔值为真,返回true,不然返回false

运用Array.some()连系fn检测一个数组中挪用指定断言要领后至少有一个效果布尔值为真。

➜  code cat anyBy.js
const anyBy = (arr, fn) => arr.some(fn);

console.log(anyBy([0, 1, 2, 0], x => x >= 2));

➜  code node anyBy.js
true

any多了一个fn要领罢了,只须要把some的参数换成fn就行,这没啥可说的。

bifurcate

Splits values into two groups. If an element in filter is truthy, the corresponding element in the collection belongs to the first group; otherwise, it belongs to the second group.

Use Array.reduce() and Array.push() to add elements to groups, based on filter.

const bifurcate = (arr, filter) =>
  arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);

把一个数组破裂成两组。假如一个元素在filter中对应值是truthy,那末响应位置的被破裂元素归属于第一个组,不然归属于第二个组。

运用Array.reduce()Array.push()filter的基本上把待破裂的元素添加到响应的组中。

➜  code cat bifurcate.js
const bifurcate = (arr, filter) => arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);

console.log(bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]));

➜  code node bifurcate.js
[ [ 'beep', 'boop', 'bar' ], [ 'foo' ] ]

reduce初始值acc是一个含有两个空数组的二维数组[[], []],遍历历程当中去推断对应索引filter的值filter[i] 是不是为truthy,若真,则把当前索引对应元素val加到acc[0]中;不然加到acc[1]中。遍历完毕,分组完成。

bifurcateBy

Splits values into two groups according to a predicate function, which specifies which group an element in the input collection belongs to. If the predicate function returns a truthy value, the collection element belongs to the first group; otherwise, it belongs to the second group.

Use Array.reduce() and Array.push() to add elements to groups, based on the value returned by fn for each element.

const bifurcateBy = (arr, fn) =>
  arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);

依据供应的断言要领将一个数组破裂成两组。假如断言效果为truthy,该元素将被分配到第一组,不然分配在第二组。

运用Array.reduce()Array.push()在断言要领fn的基本大将待破裂的元素添加到响应的组中。

➜  code cat bifurcateBy.js
const bifurcateBy = (arr, fn) => arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);

console.log(bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b'));
➜  code node bifurcateBy.js
[ [ 'beep', 'boop', 'bar' ], [ 'foo' ] ]

bifurcate比拟差别的处所是:

(acc[fn(val, i) ? 0 : 1].push(val), acc)

这里是对数组的元素val挪用指定要领,而bifurcate是对应位置filter[i]的直接效果。其他都是一样的。这也很好理解了。

    原文作者:supermao
    原文地址: https://segmentfault.com/a/1190000013305290
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞