簡體   English   中英

JavaScript:在對象的兩個 Arrays 中查找匹配和差異

[英]JavaScript: Find Matches AND Differences in two Arrays of Objects

好的,所以這是一個艱難的過程。 我認為。

我有兩個 arrays 對象,其中包含一些有關 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)
  • 如何檢查環境之間的對象匹配,同時仍捕獲不匹配的對象。 使用嵌套循環會導致大量重復和誤報問題
  • 我不確定存儲 output 的最佳方式。 可能類似於: [{ "Pod Name": "foo", "Image_Env_1": foo:1.0.0", "Image_Env_2": foo:1.0.0"}...並留下空白字符串(如表)用於不匹配情況下的值。 但這可能會與foo pod 中具有不同圖像標簽的其他圖像發生沖突。

所以Env1數組看起來像這個片段:

 [ { "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" } } ]

您可以編寫一個小助手方法來聚合來自您的 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"]
}

這非常艱難:但我認為這個過程可以分為兩個主要階段:

  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);
});

此時,這就是“查找匹配和差異”步驟。

繼續下一步“將信息轉換成有用的東西”是不太特定於簡單集合操作的部分,所以我不能就此給出合理的建議。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM