需要一些有关如何在JavaScript中使用函数式编程来重用函数的想法

时间:2018-09-11 05:33:55

标签: javascript functional-programming

这是我的jsfiddle:https://jsfiddle.net/kpam8g79/9/

我有一个函数findCommon:

function findCommon(ar1, ar2, ar3)
{
    // Initialize starting indexes for ar1[], ar2[] and ar3[]
    let i = 0, j = 0, k = 0;

    // Iterate through three arrays while all arrays have elements
    while (i < ar1.length && j < ar2.length && k < ar3.length)
    {
         // If x = y and y = z, print any of them and move ahead
         // in all arrays
         if (ar1[i] == ar2[j] && ar2[j] == ar3[k])
         {   console.log(ar1[i]+" ");   i++; j++; k++; }

         // x < y
         else if (ar1[i] < ar2[j])
             i++;

         // y < z
         else if (ar2[j] < ar3[k])
             j++;

         // We reach here when x > y and z < y, i.e., z is smallest
         else
             k++;
    }
}

我的数据集如下:

const ar1 = [1, 2, 3, 6, 8];

但是当我的数据集是一个对象数组时

const oAr1 = ar1.map(v => ({value: v, display: `value ${v}`}));

我仍然想获得共同的价值观。

我可以将oAr1映射到ar1并调用findCommon函数,但这可能不起作用。我还可以修改find​​Common函数以采用对象数组而不是数字数组,但是我想重用findCommon。我想知道是否可以使用函数式编程来以某种方式组合两个函数,以便可以重用findCommon。

我想知道如何做到这一点...

2 个答案:

答案 0 :(得分:3)

您可以在findCommon上添加一个可选参数,默认为x => x

这使您可以传递一个函数,该函数描述查找要比较的值所需的逻辑。

const ar1 = [1, 2, 3, 6, 8];
const ar2 = [1, 5, 6, 9];
const ar3 = [1, 4, 5, 6];

const oAr1 = ar1.map(v => ({value: v, display: `value ${v}`}));
const oAr2 = ar2.map(v => ({value: v, display: `value ${v}`}));
const oAr3 = ar3.map(v => ({value: v, display: `value ${v}`}));

findCommon(ar1, ar2, ar3);
findCommon(oAr1, oAr2, oAr3, o => o.value);

function findCommon(ar1, ar2, ar3, getValue = x => x)
{
    // Initialize starting indexes for ar1[], ar2[] and ar3[]
    let i = 0, j = 0, k = 0;

    // Iterate through three arrays while all arrays have elements
    while (i < ar1.length && j < ar2.length && k < ar3.length)
    {
         var x1 = getValue(ar1[i]);
         var x2 = getValue(ar2[j]);
         var x3 = getValue(ar3[k]);
         
         // If x = y and y = z, print any of them and move ahead
         // in all arrays
         if (x1 === x2 && x2 === x3)
         {   console.log(x1, ar1[i]);   i++; j++; k++; }

         // x < y
         else if (x1 < x2)
             i++;

         // y < z
         else if (x2 < x3)
             j++;

         // We reach here when x > y and z < y, i.e., z is smallest
         else
             k++;
    }
}

答案 1 :(得分:1)

一种方法是添加一个比较函数(例如Java的Comparator<>)作为参数。

// default comparator
function defCompare(x, y) { return x > y ? 1 : x < y ? -1 : 0; }

function findCommon(ar1, ar2, ar3, cmp = defCompare)
{
    let i = 0, j = 0, k = 0;
    while (i < ar1.length && j < ar2.length && k < ar3.length)
    {
         // call the custom comparator
         let c1 = cmp(ar1[i], ar2[j]);
         let c2 = cmp(ar2[j], ar3[k]);

         if (c1 == 0 && c2 == 0)
         {   console.log(ar1[i] + " ");   i++; j++; k++; }

         else if (c1 == -1)
             i++;
         else if (c2 == -1)
             j++;
         else
             k++;
    }
}

// custom comparator for the objects
function customCompare(x, y) { return defCompare(x.value, y.value); }
const common2 = findCommon(oAr1, oAr2, oAr3, customCompare);

这正常工作...除了console.log本身打印对象之外。一种解决方法是将比较器更改为“值提取器”函数,该函数返回要与之进行比较的数量:

// default: just return itself
function defValue(x) { return x; }

function findCommon(ar1, ar2, ar3, val = defValue)
{
    let i = 0, j = 0, k = 0;
    while (i < ar1.length && j < ar2.length && k < ar3.length)
    {
         // call the value extractor
         let v1 = val(ar1[i]);
         let v2 = val(ar2[j]);
         let v3 = val(ar3[k]);

         if (v1 == v2 && v2 == v3)
         {   console.log(v1 + " ");   i++; j++; k++; }

         else if (v1 < v2)
             i++;
         else if (v2 < v3)
             j++;
         else
             k++;
    }
}

// custom extractor for objects
function customValue(x) { return x.value; }
const common2 = findCommon(oAr1, oAr2, oAr3, customValue);

对于您的示例,这将按预期打印2 8