Thread overview
Comparison of multidimensional associative arrays
Feb 08, 2023
Alexander Zhirov
Feb 08, 2023
Ali Çehreli
Feb 08, 2023
Alexander Zhirov
Feb 08, 2023
Anonymouse
Feb 08, 2023
Alexander Zhirov
Feb 08, 2023
Ali Çehreli
Feb 08, 2023
Alexander Zhirov
Feb 08, 2023
Anonymouse
February 08, 2023

Not an easy task for me, maybe you can advise your compact solution. There are two associative arrays of type string[string][int]. It is necessary to find the differences and return them when comparing:

[
    6:["id":"6", "deleted":"f", "name":"6.2_test"],
    5:["id":"5", "deleted":"f", "name":"5.6_test"],
    4:["id":"4", "deleted":"f", "name":"6.2_hwlister"],
    3:["id":"3", "deleted":"f", "name":"5.6_hwlister"],
    2:["id":"2", "deleted":"f", "name":"6.2"],
    1:["id":"1", "deleted":"f", "name":"5.6"]
]

[
    4:["id":"4", "deleted":"f", "name":"6.2_hwlister"],
    3:["id":"3", "deleted":"f", "name":"5.6_hwlister"],
    2:["id":"2", "deleted":"f", "name":"6.2"],
    1:["id":"1", "deleted":"f", "name":"5.6"]
]
February 08, 2023
On 2/8/23 09:55, Alexander Zhirov wrote:
> the differences

Is it considered a difference if a key exists but the value is different? Or is that an error case if you encounter that?

> return them when comparing:

The representation seems difficult as well. When given this:

>      6:["id":"6", "deleted":"f", "name":"6.2_test"],

and that:

>      6:["id":"6", "deleted":"f" ],

Should the difference be

  6:["name":"6.2_test"] ?

And how to represent "missing from inner AA"?

Just because this sounds complicated, I hope the data structure can be designed differently to be more friendly to this operation. (?)

Ali

February 08, 2023

On Wednesday, 8 February 2023 at 18:08:40 UTC, Ali Çehreli wrote:

>

Just because this sounds complicated, I hope the data structure can be designed differently to be more friendly to this operation. (?)

Ali

This is the result of an SQL query. Roughly speaking, I need to compare the result of queries from two different databases and find different ones. The tables are the same, the only difference is in the content.

February 08, 2023

On Wednesday, 8 February 2023 at 17:55:03 UTC, Alexander Zhirov wrote:

>

Not an easy task for me, maybe you can advise your compact solution. There are two associative arrays of type string[string][int]. It is necessary to find the differences and return them when comparing:

Can you explain how you determine how/if two entries are different?

February 08, 2023

On Wednesday, 8 February 2023 at 18:57:00 UTC, Anonymouse wrote:

>

Can you explain how you determine how/if two entries are different?

I apologize. I have not written, in fact, what I need to get.

Array A

[
    4:["id":"4", "deleted":"f", "name":"6.2"],
    3:["id":"3", "deleted":"f", "name":"5.6_hwlister"],
    2:["id":"2", "deleted":"t", "name":"6.2"],
    1:["id":"1", "deleted":"f", "name":"5.6"]
]

Array B

[
    6:["id":"6", "deleted":"f", "name":"6.2_test"],
    5:["id":"5", "deleted":"f", "name":"5.6_test"],
    4:["id":"4", "deleted":"f", "name":"6.2_hwlister"],
    3:["id":"3", "deleted":"f", "name":"5.6_hwlister"],
    2:["id":"2", "deleted":"f", "name":"6.2"],
    1:["id":"1", "deleted":"f", "name":"5.6"]
]

Diff:

[
    6:["id":"6", "deleted":"f", "name":"6.2_test"],
    5:["id":"5", "deleted":"f", "name":"5.6_test"],
    4:["id":"4", "deleted":"f", "name":"6.2_hwlister"],
    2:["id":"2", "deleted":"f", "name":"6.2"]
]

That is, the result is arrays of table B that are missing OR not equal to arrays in table A.

February 08, 2023
On 2/8/23 11:04, Alexander Zhirov wrote:

> That is, the result is arrays of table B that are missing OR not equal
> to arrays in table A.

This should do it:

alias MyType = string[string][int];

// 'a' is subtracted from 'b'
MyType difference(MyType b, MyType a) {
    MyType result;

    foreach (kv; b.byKeyValue) {
        auto existing = kv.key in a;

        if (!existing || (*existing != kv.value)) {
            result[kv.key] = kv.value;
        }
    }

    return result;
}

void main() {
    auto a = [
        4:["id":"4", "deleted":"f", "name":"6.2"],
        3:["id":"3", "deleted":"f", "name":"5.6_hwlister"],
        2:["id":"2", "deleted":"t", "name":"6.2"],
        1:["id":"1", "deleted":"f", "name":"5.6"]
    ];

    auto b = [
        6:["id":"6", "deleted":"f", "name":"6.2_test"],
        5:["id":"5", "deleted":"f", "name":"5.6_test"],
        4:["id":"4", "deleted":"f", "name":"6.2_hwlister"],
        3:["id":"3", "deleted":"f", "name":"5.6_hwlister"],
        2:["id":"2", "deleted":"f", "name":"6.2"],
        1:["id":"1", "deleted":"f", "name":"5.6"]
    ];

    auto expected = [
        6:["id":"6", "deleted":"f", "name":"6.2_test"],
        5:["id":"5", "deleted":"f", "name":"5.6_test"],
        4:["id":"4", "deleted":"f", "name":"6.2_hwlister"],
        2:["id":"2", "deleted":"f", "name":"6.2"]
    ];

    auto diff = difference(b, a);

    import std.format;
    assert(diff == expected, format!"UNEXPECTED: %s"(diff));
}

Ali

February 08, 2023

On Wednesday, 8 February 2023 at 19:32:22 UTC, Ali Çehreli wrote:

>

This should do it:
[...]

Yes, it works! I'll try it tomorrow on a large array of data. Thank you very much!
This turns out to be a simple loop with a comparison of the existence of a key (whether it is included in an array or not) and a comparison of an existing array as a value with another array by this key. I wonder if can add this to lambda? In one line.

February 08, 2023

On Wednesday, 8 February 2023 at 19:04:15 UTC, Alexander Zhirov wrote:

>

[...]

I would write a data structure and use struct members to reason about things, but that's probably just preference.

import std;

struct DatabaseEntry
{
    int id = -1;
    string deleted;
    string name;

    this(string[string] aa)
    {
        this.id = aa["id"].to!int;
        this.deleted = aa["deleted"];
        this.name = aa["name"];
    }

    auto opEquals(typeof(this) that) const
    {
        return
            (this.id == that.id) &&
            (this.deleted == that.deleted) &&
            (this.name == that.name);
    }
}

auto buildSortedEntryRange(string[string][int] aa)
{
    return aa
        .byValue
        .map!(entry => DatabaseEntry(entry))
        .array
        .sort!((a,b) => a.id < b.id);
}

void main()
{
    auto arrayA =
    [
        4:["id":"4", "deleted":"f", "name":"6.2"],
        3:["id":"3", "deleted":"f", "name":"5.6_hwlister"],
        2:["id":"2", "deleted":"t", "name":"6.2"],
        1:["id":"1", "deleted":"f", "name":"5.6"]
    ];

    auto arrayB =
    [
        6:["id":"6", "deleted":"f", "name":"6.2_test"],
        5:["id":"5", "deleted":"f", "name":"5.6_test"],
        4:["id":"4", "deleted":"f", "name":"6.2_hwlister"],
        3:["id":"3", "deleted":"f", "name":"5.6_hwlister"],
        2:["id":"2", "deleted":"f", "name":"6.2"],
        1:["id":"1", "deleted":"f", "name":"5.6"]
    ];

    auto entriesFromA = buildSortedEntryRange(arrayA);
    auto entriesFromB = buildSortedEntryRange(arrayB);
    auto range = zip(StoppingPolicy.longest, entriesFromA, entriesFromB);

    foreach (entryA, entryB; range)
    {
        if (entryA != entryB)
        {
            writeln(entryB);
            // ...
        }
    }
}

Output is:

DatabaseEntry(2, "f", "6.2")
DatabaseEntry(4, "f", "6.2_hwlister")
DatabaseEntry(5, "f", "5.6_test")
DatabaseEntry(6, "f", "6.2_test")