Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

函数式编程理解与reduce、map、filter等方法实践 #4

Open
xuqinggang opened this issue May 24, 2018 · 0 comments
Open

函数式编程理解与reduce、map、filter等方法实践 #4

xuqinggang opened this issue May 24, 2018 · 0 comments

Comments

@xuqinggang
Copy link
Owner

xuqinggang commented May 24, 2018

函数式编程reduce、map、filter、find等应用实践

对reduce、map、filter等方法的讲解,可以看这篇文章ccforward/cc#59

// 输入为state和originData变量
// 输出为:
{
    houseTypeShared: '2居_3居',
    houseTypeWhole: '2居',
};
// state和originData变量如下:
// state
const state = {
    sharedRooms: { 0: false, 1: true, 2:true },
    wholeRooms: { 2: false, 3: true },
};

// 源数据
const originData = {
    sharedRooms: [
        {
            unique: true,
            text: '不限',
            value: 'UNLIMITED',
        },
        {
            text: '2居',
            value: 'TWO',
        },
        {
            text: '3居',
            value: 'THREE',
        },
        {
            text: '3居+',
            value: 'THREE_MORE',
        },
    ],
    wholeRooms: [
        {
            unique: true,
            text: '不限',
            value: 'UNLIMITED',
        },
        {
            text: '1居',
            value: 'ONE',
        },
        {
            text: '2居',
            value: 'TWO',
        },
        {
            text: '2居+',
            value: 'TWO_MORE',
        },
    ]
};
// (1)正常写法,可能会像下面这样
function compute(state, originData) {
    const TypeMapParamKey = {
        sharedRooms: 'houseTypeShared',
        wholeRooms: 'houseTypeWhole',
    };

    const paramArr = Object.keys(state)
        .map(type => {
            const typeDataArr = originData[type];
            const typeStateObj = state[type];
            const textArr = [];
            Object.keys(typeStateObj)
                .forEach((index) => {
                        const bool = typeStateObj[index];
                        if (bool) {
                            textArr.push(typeDataArr[index].text);
                        }
                })
            const textRt = textArr.split('_');
            return {
                [TypeMapParamKey[type]]: textRt,
            };
        });
    const paramsObj = {};
    paramArr.forEach(param => Object.assign(paramsObj, param));

    return paramsObj;
}

// (2)利用map, reduce, filter等函数式方法,计算出结果。
function compute(state, originData) {
    const TypeMapParamKey = {
        sharedRooms: 'houseTypeShared',
        wholeRooms: 'houseTypeWhole',
    };

    retrun Object.keys(state)
        .map(type => {
            const rtText = Object.keys(state[type])
                .filter(index => state[type][index])
                .map(index => originData[type][index].text)
                .reduce((rt, text, index) =>
                    (`${rt}` + (index === 0 ? '' : '_') + `${text}`),
                    '',
                );
            return {
                [TypeMapParamKey[type]]: rtText,
            };
        })
        .reduce((rt, item) => Object.assign(rt, item), {})
}

比较上述两者写法,从代码行数上来说,二者差不读。

方法(1)更加的过程式,一步步的计算出需要的结果,利用上一步结果计算出下一步的。可能也比较易读。

方法(2)更加的函数式,充分利用各种函数式方法,简化操作,计算出需要的。

其实感觉方法(2)比方法(1)更加充分的利用reduce,把数组中的多个数据通过某种操作合并成一个数据,而不是简单的遍历数组。
细心的同学发现:方法(2)利用filter和map其实遍历了两遍数组,而方法(1)遍历一遍筛选出text数组
可以看下JavaScript 函数式编程存在性能问题么?解决疑惑。

在这里强调,大家还是应该尽可能从函数式编程的角度,多利用函数式方法(filter,map,reduce等)解决问题

优点:

  1. 通过链式调用,代码精简
  2. map,reduce,filter等方法更具语义化,

坏处:

  1. 初次阅读,难以阅读理解(其实写习惯,就很容易理解了)
  2. 性能会有损牺牲(但性能从现在以后来讲,应该更不是问题,毕竟硬件性能会越来越高,或许以后也会加入惰性计算优化map、reduce等方法)。性能问题可以利用实现惰性计算的loadsh库ramda库解决
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant