gpt4 book ai didi

javascript - 使用函数式 JavaScript 将数组拆分为两个不同的数组

转载 作者:可可西里 更新时间:2023-11-01 02:33:07 24 4
gpt4 key购买 nike

我想知道使用 JavaScript 将数组拆分为两个不同数组的最佳方法是什么,但又要将其保留在函数式编程领域。

假设这两个数组应该根据某些逻辑创建。例如拆分一个数组应该只包含少于四个字符的字符串,另一个数组包含其余的字符串。

const arr = ['horse', 'elephant', 'dog', 'crocodile', 'cat'];

我想过不同的方法:

过滤器:

const lessThanFour = arr.filter((animal) => {
return animal.length < 4;
});
const fourAndMore = arr.filter((animal) => {
return animal.length >= 4;
});

对我来说,这个问题是你必须检查你的数据两次,但它的可读性很强。如果你有一个相当大的数组,那么两次这样做会有很大的影响吗?

减少:

const threeFourArr = arr.reduce((animArr, animal) => {
if (animal.length < 4) {
return [[...animArr[0], animal], animArr[1]];
} else {
return [animArr[0], [...animArr[1], animal]];
}
}, [[], []]);

其中数组的 0 索引包含少于四的数组,而 1 索引包含多于三的数组。

不太喜欢这个,因为好像数据结构要出点问题,看是一个数组的数组。我考虑过使用 reduce 构建一个对象,但我无法想象它会比数组解决方案中的数组更好。

我已经设法在网上以及 Stack Overflow 上查看了类似的问题,但是其中许多问题通过使用 push() 打破了不变性的想法,或者它们的实现非常难以理解,这在我的意见打破了函数式编程的表现力。

还有其他方法吗? (当然是功能性的)

最佳答案

collateBy

我刚刚分享了一个 similar answer here

我更喜欢这个解决方案,因为它抽象了整理,但允许您使用高阶函数控制如何项目整理。

请注意我们如何不提及 animal.length< 4animals[0].push里面collateBy .此过程不知道您可能正在整理的数据种类

// generic collation procedure
const collateBy = f => g => xs => {
return xs.reduce((m,x) => {
let v = f(x)
return m.set(v, g(m.get(v), x))
}, new Map())
}

// custom collator
const collateByStrLen4 =
// collate by length > 4 using array concatenation for like elements
// note i'm using `[]` as the "seed" value for the empty collation
collateBy (x=> x.length > 4) ((a=[],b)=> [...a,b])

// sample data
const arr = ['horse','elephant','dog','crocodile','cat']

// get collation
let collation = collateByStrLen4 (arr)

// output specific collation keys
console.log('greater than 4', collation.get(true))
console.log('not greater than 4', collation.get(false))

// output entire collation
console.log('all entries', Array.from(collation.entries()))

检查 other answer I posted查看其他用法品种。这是一个非常方便的过程。


bifilter

这是另一种捕获过滤函数输出的解决方案,而不是像 Array.prototype.filter 那样丢弃过滤后的值。

这基本上就是你的 reduce实现确实如此,但它被抽象为一个通用的参数化过程。它使用Array.prototype.push但在闭包体中,局部突变通常被认为是 OK。

const bifilter = (f,xs) => {
return xs.reduce(([T,F], x, i, arr)=> {
if (f(x, i, arr) === false)
return [T, [...F,x]]
else
return [[...T,x] ,F]
}, [[],[]])
}

const arr = ['horse','elephant','dog','crocodile','cat']

let [truthy,falsy] = bifilter(x=> x.length > 4, arr)
console.log('greater than 4', truthy)
console.log('not greater than 4', falsy)

虽然它可能更直接一些,但它不如collateBy 强大。 .无论哪种方式,选择您喜欢的任何一种,必要时根据您的需要进行调整,然后玩得开心!


如果这是您自己的应用程序,请发疯并将其添加到 Array.prototype

// attach to Array.prototype if this is your own app
// do NOT do this if this is part of a lib that others will inherit
Array.prototype.bifilter = function(f) {
return bifilter(f,this)
}

关于javascript - 使用函数式 JavaScript 将数组拆分为两个不同的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38860643/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com