【问题标题】:JavaScript: Find Matches AND Differences in two Arrays of ObjectsJavaScript:在两个对象数组中查找匹配和差异
【发布时间】:2020-09-19 23:33:00
【问题描述】:

好的,所以这是一个艰难的过程。我想。

我有两个对象数组,其中包含一些关于 pod 的信息。我希望提供环境的并排比较,以显示 pod 包含完全相同的图像的位置;诀窍是我需要捕捉图像不匹配的豆荚。结果将呈现在一个看起来像这样的表上(至少作为第一次迭代):

|---------------------|------------------|------------------|
|      Pod Name       | Image from Env1  |  Image from Env2 |
|---------------------|------------------|------------------|
|          foo        |     foo:1.0.0    |     foo:1.0.0    |   <---- images match
|---------------------|------------------|------------------| 
|          foo        |   foobar:1.0.0   |                  |   <---- No match for image tag; image name different from the pod name as the pods may contain multiple images
|---------------------|------------------|------------------| 
|          foo        |                  |    foobar:2.0.0  |   <---- As above
|---------------------|------------------|------------------|
|          bar        |     bar:2.0.0    |     bar:2.0.0    |   <---- images match 
|---------------------|------------------|------------------|
|          baz        |     baz:1.0.0    |                  |   <----
|---------------------|------------------|------------------|         Note the 'no match'; so own row for now
|          baz        |                  |     baz:2.0.0    |   <----
|---------------------|------------------|------------------|

稍后我将使用 CSS 突出显示匹配与差异。

我最苦恼的事情是:

  • Pod 可能有超过 1 个图像。这些图像中的一张可能在环境之间匹配,但另一张可能不匹配。当有多个图像时,该 pod 内的标签会有所不同(参见上表中的 foo pod)
  • 如何检查环境之间的对象匹配,同时仍捕获不匹配的对象。使用嵌套循环会导致大量重复和漏报问题
  • 我不确定存储输出的最佳方式。可能类似于:[{ "Pod Name": "foo", "Image_Env_1": foo:1.0.0", "Image_Env_2": foo:1.0.0"}... 并在不匹配的情况下为值留下空白字符串(如表中的空白单元格)。但这可能会与 foo pod 中具有不同图像标签的其他图像发生冲突。

所以Env1 数组看起来像这样 sn-p:

[
    {
        "Image": {
            "S": "foo:1.0.0"
        },
        "Pod Name": {
            "S": "foo"
        }
    },
    {
        "Image": {
            "S": "foobar:0.2.0"
        },
        "Pod Name": {
            "S": "foo"
        }
    },
    {
        "Image": {
            "S": "bar:1.0.0"
        },
        "Pod Name": {
            "S": "bar"
        }
    },
    {
        "Image": {
            "S": "baz:1.0.0"
        },
        "Pod Name": {
            "S": "baz"
        }
    },
    {
        "Image": {
            "S": "qux:1.0.0"
        },
        "Pod Name": {
            "S": "foo"
        }
    }
]

Env2数组:

[
    {
        "Image": {
            "S": "foo:2.0.0"
        },
        "Pod Name": {
            "S": "foo"
        }
    },
    {
        "Image": {
            "S": "foobar:0.2.0"
        },
        "Pod Name": {
            "S": "foo"
        }
    },
    {
        "Image": {
            "S": "bar:1.0.0"
        },
        "Pod Name": {
            "S": "bar"
        }
    },
    {
        "Image": {
            "S": "baz:3.0.0"
        },
        "Pod Name": {
            "S": "baz"
        }
    }
]

【问题讨论】:

    标签: javascript node.js json


    【解决方案1】:

    这太难了!但我认为这个过程可以分为两个主要阶段:

    1. 寻找匹配和差异。
    2. 将这些信息转化为有用的东西。

    第一步可以进一步分解为对原始数据进行操作,然后对其进行处理。

    在处理 Pod Name 等类别时,我喜欢做的是创建包含 Set 对象的 Map 对象。在这种情况下,它可能看起来像这样:

    // Let's assume Env1 is loaded already.
    const podNameMap1 = new Map();
    Env1.forEach( (value, index) => {
        // Here 'value' is element in Env1
    
        const podName = value['Pod Name'].S;
        const podValue = podNameMap.get(podName);
        // returns undefined if it does not exist
    
        if (!podValue) {
            podNameMap.set(podName, new Set(value['Image'].S) );
            // If there is no podValue, set podName to a new Set with the images in it.
        } else {
            // Here there is a podValue, and we can add a new member to the Set.
            podValue.add(value['Images'].S);
            // podValue is a Set object which means the map value needs to be set one time.
        }
    });
    

    最后,podNameMap1 包含所有 pod 及其所有图像。下一步就是对Env2做同样的事情,此时会有两张不同pod名称和图片的映射。

    之后就可以进行比较了,比创建地图要复杂:

    // Let's assume podNameMap1 and podNameMap2 are both loaded.
    // I don't know if it's possible for pods to be mismatched,
    // I'm going to assume they are cannot be.
    
    // Images in both
    const inBothEnvsMap = new Map();
    // Images in env1 but not env2
    const inEnv1Map = new Map();
    // Images in env2 but not env1
    const inEnv2Map = new Map();
    
    podNameMap1.forEach( (imageSet1, podName) => {
        // Here, imageSet1 and podName are self explanitory
        const imageSet2 = podNameMap1.get(podName); // assuming this is always the case
    
        // Computing the set intersections n stuff
        const inEnv1 = new Set();
        const inEnv2 = new Set();
        const inBothEnvs = new Set();
    
        // Note: I wish JS had built in set operations because there's probably
        // a better way to do this but alas...
        imageSet1.forEach( image => {
            if (imageSet2.has(image))
                inBothEnvs.add(image);
            else // in imageSet1 only
                inEnv1.add(image);
        });
        // now inEnv1 AND inBothEnvs are complete
    
        imageSet2.forEach( image => {
            if (!imageSet1.has(image))
                inEnv2.add(image);
        });
    
        // now this pod is done
        inBothEnvsMap.set(podName, inBothEnvs);
        inEnv1Map.set(podName, inEnv1);
        inEnv2Map.set(podname, inEnv2);
    });
    

    此时,这是“寻找匹配和差异”步骤。

    进入下一步“将信息转化为有用的东西”是不太特定于简单集合操作的部分,因此我无法就此给出合理的建议。

    【讨论】:

    • 感谢您的回复!看起来不错,我正在尝试中。第二个sn-p中的“key”,跟什么有关?目前获得'key' is not defined
    【解决方案2】:

    您可以编写一个小助手方法来聚合来自您的 env 文件的信息,即首先按 pod 分组,然后聚合使用的图像。过滤在多个环境中使用图像的条目应该是微不足道的。

    类似的东西(请注意,这适用于任意数量的环境):

    function getAggregatedPodInfos(...environments) {
        const aggregatedInfos = {pods: {}, environments: []};
        environments.forEach(env => addEnvironmentInfos(env, aggregatedInfos))
        return aggregatedInfos;
    }
    
    function addImageInfoByEnvironment(pod, environment, imageName) {
        if (!pod.imageInfo[environment.envName]) {
            pod.imageInfo[environment.envName] = [];
        }
        pod.imageInfo[environment.envName].push(imageName)
    }
    
    function addEnvironmentInfos(environment, envInfo) {
        envInfo.environments.push(environment.envName);
        for (const envEntry of environment.data) {
            const podName = envEntry["Pod Name"]["S"];
            const imageName = envEntry["Image"]["S"];
            if (!envInfo.pods[podName]) {
                envInfo.pods[podName] = {imageInfo: {}};
            }
            addImageInfoByEnvironment(envInfo.pods[podName], environment, imageName);
        }
    }
    
    const res = getAggregatedPodInfos({envName: 'env1', data: env1}, {envName: 'env2', data: env2});
    console.log(JSON.stringify(res))
    

    这将打印:

    {
        "pods": {
            "foo": {
                "imageInfo": {
                    "env1": ["foo:1.0.0", "foobar:0.2.0", "qux:1.0.0"],
                    "env2": ["foo:2.0.0", "foobar:0.2.0"]
                }
            },
            "bar": {
                "imageInfo": {
                    "env1": ["bar:1.0.0"],
                    "env2": ["bar:1.0.0"]
                }
            },
            "baz": {
                "imageInfo": {
                    "env1": ["baz:1.0.0"],
                    "env2": ["baz:3.0.0"]
                }
            }
        },
        "environments": ["env1", "env2"]
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-28
      • 1970-01-01
      • 2018-04-05
      • 2022-01-04
      • 2019-11-02
      • 2013-09-16
      • 1970-01-01
      相关资源
      最近更新 更多