有没有其他方法可以使用地图,过滤器,缩小...来解决此forEach问题?

时间:2018-11-04 06:26:37

标签: javascript functional-programming

如果我有两个像这两个对象的数组

const x = [{id: 1, a: 5}, {id: 2, a:10}, {id: 3, a: 12}];

const y = [{id: 4, a: 0}, {id: 2, a: 0}, {id: 3, a: 0}];

输出应为代表y的新数组 但是经过一些修改,如果y中的项目具有id与x中的项目匹配,则a的值应与x相同,因此输出应为

[{id: 4, a: 0}, {id: 2, a: 10}, {id: 3, a: 12}]

这是我的解决方法

const z = [...y];
z.forEach(el => x.map(ele =>  el.a = el.id === ele.id ? ele.a : el.a));

这是我在项目中所做的一个简单实现,我关心性能,并且我看到克隆数组z = [...y]的步骤可能会很昂贵,因此我正在寻找使用返回函数的解决方案新数组mapfilterreduce ...,

我尝试嵌套mapfilterfind ...,但是我以复杂的解决方案作为结尾,那么还有其他解决方案在同时具有更高的性能和简单性吗? / p>

4 个答案:

答案 0 :(得分:2)

您可以通过单次迭代从xy创建一个xObj,而不是为x遍历y并在(constant lookup O(1) )上循环,只需检查它是否存在如果是,请在xObj const x = [{id: 1, a: 5}, {id: 2, a:10}, {id: 3, a: 12}]; const y = [{id: 4, a: 0}, {id: 2, a: 0}, {id: 3, a: 0}]; var xObj = {}; x.forEach(function(val){ xObj[val.id] = val.a; }); const newY = y.reduce(function(o,i){ if(xObj.hasOwnProperty(i.id)){ i.a = xObj[i.id]; } o.push(i); return o; },[]); console.log(newY); 中进行更新,否则请使用现有值进行更新。

public class ArrayExample {

    public static void main(String[] args) {            
        int a[]= {12,3,-1,4,-2,8,-9,-6,4,78};
        int len=a.length;
        int i,j,k;
        int pcount=0,ncount=0;
        int b[]=new int[len];

        for(i=0;i<len;i++)   // for counting positive & negative nos.
        {
            if(a[i]>0)
            {
                pcount++;
            }
            else
                ncount++;
        }

        //Buffer Array 
        int pos[]=new int[pcount];
        int neg[]=new int[ncount];

        // Inserting into resp. arrays
        for(i=0,j=0,k=0;i<len;i++)
        {
            if(a[i]<0 && j<ncount)
            {
                neg[j]=a[i];
                j++;

            }
            if(a[i]>0 && k<pcount)
            {
                pos[k]=a[i];
                k++;

            }               
        }
        System.out.println("Arr "+Arrays.toString(a));
        System.out.println("Pos "+Arrays.toString(pos));
        System.out.println("Neg "+Arrays.toString(neg));


//Insert into final array
        for(i=0,j=0,k=0;i<(len);i++)
        {


            if(i%2==0 && j<pcount)
            {
                b[i]=pos[j];
                j++;

            }
            if(i%2!=0 && k<ncount)
            {
                b[i]=neg[k];
                k++;
            }   
        }
        //Final no. correction 
        System.out.println("Final "+Arrays.toString(b));

    }
}

答案 1 :(得分:1)

对于这样的问题,您应该关心创建新数组的计算费用,而关心通过多个数组运行的大O费用 more 多次。您的解决方案和@NitishNarang发布的另一种解决方案似乎都为O(n ^ 2),因为随着数组的增大,求解所需的步骤数呈指数增长。

我个人将只创建一个新的Map()并逐个检查每个项目,仅当与该ID对应的Map()的值大于该值时,才将其添加到a当前存储的一个。除了添加唯一的ID值之外,基本上这是一个稍微复杂的排序工作。

const x = [{id: 1, a: 5}, {id: 2, a:10}, {id: 3, a: 12}];
const y = [{id: 4, a: 0}, {id: 2, a: 0}, {id: 3, a: 0}];
const myMap = new Map();
for (const ea of x) {
  if (!myMap.has(ea.id) || ea.a >= myMap.get(ea.id).a) {
    myMap.set(ea.id, ea);
  }
}
for (const ea of y) {
  if (!myMap.has(ea.id) || ea.a >= myMap.get(ea.id).a) {
    myMap.set(ea.id, ea);
  }
}
const result = [...myMap.values()];

此解决方案为O(n),即线性的,这意味着如果您向数组xy或两者中添加10或100或1000个以上的项目,则只会添加那么多运行解决方案的更多步骤,而不是10 ^ 2或100 ^ 2或1000 ^ 2,因为您必须对照每个数组中的每个其他项目检查每个数组中的每个项目(就像您对原始解决方案所做的那样。)

编辑:正如@SZenC所指出的,上述解决方案由于将两个数组组合在一起而不太正确。为了仅在项目最初存在于数组y中时才有选择地匹配项,只需先对y进行迭代,然后在对x进行迭代时仅替换值(如果它们已经存在于映射中) :

const x = [{id: 1, a: 5}, {id: 2, a:10}, {id: 3, a: 12}];
const y = [{id: 4, a: 0}, {id: 2, a: 0}, {id: 3, a: 0}];
const myMap = new Map();
for (const ea of y) {
  if (!myMap.has(ea.id) || ea.a >= myMap.get(ea.id).a) {
    myMap.set(ea.id, ea);
  }
}
for (const ea of x) {
  if (myMap.has(ea.id) && ea.a >= myMap.get(ea.id).a) {
    myMap.set(ea.id, ea);
  }
}
const result = [...myMap.values()];

答案 2 :(得分:1)

使用Setids存储在x数组中,并在map数组上使用y来检查y's {{1 }}是否存在于id中。

Set

希望这会有所帮助!

答案 3 :(得分:0)

请尝试这个。它使用“ map”和“ find

sum