ENikS/LINQ

GroupBy object key failed.

QJesus opened this issue · 7 comments

import { asEnumerable as linq } from 'linq-es5';

const yx = [
    { id: '1', batchNumber: 'ZKFM1', value: 'zzz' },
    { id: '2', batchNumber: 'ZKFM', value: 'xxx' },
    { id: '1', batchNumber: 'ZKFM1', value: 'yyy' }
];

const xs = linq(yx).GroupBy(d => ({ id: d.id, b: d.batchNumber })).Select(d => {
    const t = linq(d as { id: string, batchNumber: string, value: string }[]).Select(dx => dx);
    return {
        cnt: t.Count(),
        array: t.ToArray(),
    };
}).ToArray();
console.log(JSON.stringify(xs));

the answer as blow:

[
    {
        "cnt": 1, 
        "array": [
            {
                "id": "1", 
                "batchNumber": "ZKFM1", 
                "value": "zzz"
            }
        ]
    }, 
    {
        "cnt": 1, 
        "array": [
            {
                "id": "2", 
                "batchNumber": "ZKFM", 
                "value": "xxx"
            }
        ]
    }, 
    {
        "cnt": 1, 
        "array": [
            {
                "id": "1", 
                "batchNumber": "ZKFM1", 
                "value": "yyy"
            }
        ]
    }
]

i hope it will be:

[
    {
        "cnt": 2, 
        "array": [
            {
                "id": "1", 
                "batchNumber": "ZKFM1", 
                "value": "zzz"
            }, 
            {
                "id": "1", 
                "batchNumber": "ZKFM1", 
                "value": "yyy"
            }
        ]
    }, 
    {
        "cnt": 1, 
        "array": [
            {
                "id": "2", 
                "batchNumber": "ZKFM", 
                "value": "xxx"
            }
        ]
    }
]

import { asEnumerable as linq } from 'linq-es5';
import { asEnumerable as linq } from 'linq-es2015';

both have the same result.

ENikS commented

Thank you for the report, will look into if shortly

ENikS commented

The reason you have invalid result is because of how you create your keys. In conventional code it could be presented by this notation:

        var key1 = { id: yx[0].id, b: yx[0].batchNumber };
        var key2 = { id: yx[1].id, b: yx[1].batchNumber };
        var key3 = { id: yx[2].id, b: yx[2].batchNumber };
        
        var res1 = key1 == key2; // These expected to be NOT equal 
        var res2 = key1 == key3; // These expected to be equal 

if you execute this code both res1 and res2 will be false because JavaScript treats separate objects as not equal. If you use either just id or just batchNumber it should work.

const xs = linq(yx).GroupBy(d => d.id).Select ...

THX a lot. as my issue must group by id and batchNumber, so change it as below.

linq(yx).GroupBy(d => `${d.id} ${d.batchNumber}`).Select(

this can work as expected.

otherwise:
Can override operator == or === in JavaScript ?
Or Can use for in to compare every property of an object?

I find a better way to solve this problem.Using JSON.stringify()

const yx = [
    { id: '1', batchNumber: 'ZKFM1', value: 'zzz' },
    { id: '2', batchNumber: 'ZKFM', value: 'xxx' },
    { id: '1', batchNumber: 'ZKFM1', value: 'yyy' }
];

const xs = linq(yx).GroupBy(d => JSON.stringify(({ id: d.id, b: d.batchNumber }))).Select(d => {
    const t = linq(d as { id: string, batchNumber: string, value: string }[]).Select(dx => dx);
    return {
        cnt: t.Count(),
        array: t.ToArray(),
    };
}).ToArray();
console.log(JSON.stringify(xs));
ENikS commented

.GroupBy(d => `${d.id} ${d.batchNumber}`) should be much faster but whatever works for you