代码之家  ›  专栏  ›  技术社区  ›  Radex

比较两个数组的内容

  •  1
  • Radex  · 技术社区  · 7 年前

    我需要比较两个数组(源/目标)对象的内容。

    若目标中确实存在源中的项,我应该只添加要排除的项。

    R.differenceWith() 但当目标为空时,我会遇到一个问题。

    differenceWith 把海豚放在这里,否则我可以用其他功能。请给我举个例子,谢谢!

    注:即使不使用ramda也可以回答。

    Demo

    // source
      const pathHash1 = {
        hash: "c4ca4238a0b923820dcc509a6f75849b",
        path: "./source/file1.txt"
      };
      const pathHash2 = {
        hash: "c81e728d9d4c2f636f067f89cc14862c",
        path: "./source/file2.txt"
      };
      const pathHash3 = {
        hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
        path: "./souce/file3.txt"
      };
      // target
      const pathHash4 = {
        hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
        path: "./target/file3.txt"
      };
    
    // works
    // const source = [pathHash1, pathHash2, pathHash3]
    // const target = [pathHash4]
    
    // does no work
    const source = [pathHash1, pathHash2, pathHash3]
    const target = []
    
    // result pathHash1, pathHash2
    const resultInclude = R.differenceWith((x,y)=> x.hash === y.hash, source, target)
    const resultExclude= R.differenceWith((x,y)=> x.hash !== y.hash, source, target)
    
    console.log('include',resultInclude.map(x=>x.hash))
    console.log('exclude',resultExclude.map(x=>x.hash))
    
    5 回复  |  直到 7 年前
        1
  •  3
  •   Ori Drori    7 年前

    使用 R.innerJoin 对于排除情况:

    const getInclude = R.differenceWith(R.eqProps('hash'))
    const getExclude = R.innerJoin(R.eqProps('hash'))
    
    const pathHash1 = {hash: "c4ca4238a0b923820dcc509a6f75849b",path: "./source/file1.txt"},pathHash2 = {hash: "c81e728d9d4c2f636f067f89cc14862c",path: "./source/file2.txt"},pathHash3 = {hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",path: "./souce/file3.txt"},pathHash4 = {hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",path: "./target/file3.txt"}
    
    const source1 = [pathHash1, pathHash2, pathHash3]
    const target1 = [pathHash4]
    
    const source2 = [pathHash1, pathHash2, pathHash3]
    const target2 = []
    
    const getHash = R.map(R.prop('hash'))
    
    console.log('include1', getHash(getInclude(source1, target1)))
    console.log('exclude1', getHash(getExclude(source1, target1)))
    
    console.log('include2', getHash(getInclude(source2, target2)))
    console.log('exclude2', getHash(getExclude(source2, target2)))
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
        2
  •  1
  •   GibboK    7 年前

    在香草JS中,你可以考虑使用这个版本:

      const resultInclude = pathHashListSource.filter(x => !pathHashListTarget.find(y => y.hash === x.hash));
      const resultExclude = pathHashListSource.filter(x => pathHashListTarget.find(y => y.hash === x.hash));
    
        3
  •  0
  •   customcommander    7 年前

    我想你可以用 difference differenceWith 对于简单对象。如果要在这两个视图中查找公共对象 source target innerJoin :

    const {difference, innerJoin, equals} = R;
    
    const a = [{x: 1}, {y: 2}, {z: 3}];
    const b = [{a: 0}, {x: 1}];
    
    console.log(
      difference(a, b)
    );
    
    console.log(
      innerJoin(equals, a, b)
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
        4
  •  0
  •   gaetanoM    7 年前

    你从中得到的结果 R.differenceWith() 是正确的,因为这种方法的来源是:

    var differenceWith = _curry3(function differenceWith(pred, first, second) {
        var out = [];
        var idx = 0;
        var firstLen = first.length;
        while (idx < firstLen) {
                if (!_includesWith(pred, first[idx], second) && 
                    !_includesWith(pred, first[idx], out)) {
                    out.push(first[idx]);
                }
                idx += 1;
        }
        return out;
    });
    

    正如您可以看到的,差异是使用 _包括 . 但是,当第二个数组为空时,将填充正在进行的输出数组(无重复)。

    // source
    const pathHash1 = {
        hash: "c4ca4238a0b923820dcc509a6f75849b",
        path: "./source/file1.txt"
    };
    const pathHash2 = {
        hash: "c81e728d9d4c2f636f067f89cc14862c",
        path: "./source/file2.txt"
    };
    const pathHash3 = {
        hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
        path: "./souce/file3.txt"
    };
    // target
    const pathHash4 = {
        hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
        path: "./target/file3.txt"
    };
    
    // works
    // const source = [pathHash1, pathHash2, pathHash3]
    // const target = [pathHash4]
    
    // issue
    const source = [pathHash1, pathHash2, pathHash3]
    const target = []
    
    // result pathHash1, pathHash2
    const resultInclude = R.differenceWith((x,y)=> x.hash === y.hash, source, target)
    const resultExclude= R.differenceWith((x,y)=> x.hash !== y.hash, source, target)
    
    
    console.log('include',resultInclude.map(x=>x.hash))
    console.log('exclude',resultExclude.map(x=>x.hash))
    <script src="https://cdn.jsdelivr.net/npm/ramda@latest/dist/ramda.min.js"></script>
        5
  •  0
  •   Scott Christopher    7 年前

    这里的另一个选择是建立本地 Set 目标哈希的定义和使用 R.partition 设置

    const source = [
      {
        hash: "c4ca4238a0b923820dcc509a6f75849b",
        path: "./source/file1.txt"
      },
      {
        hash: "c81e728d9d4c2f636f067f89cc14862c",
        path: "./source/file2.txt"
      },
      {
        hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
        path: "./souce/file3.txt"
      }
    ]
    
    const target = [
      {
        hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
        path: "./target/file3.txt"
      }
    ]
    
    ////
    
    const targetHashes =
      target.reduce((hashes, next) => hashes.add(next.hash), new Set)
    
    const [resultExclude, resultInclude] =
      R.partition(x => targetHashes.has(x.hash), source)
    
    ////
    
    console.log("resultInclude", resultInclude)
    console.log("resultExclude", resultExclude)
    <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>