Ad

Unique Union In Lodash

- 1 answer

I have two kind of collections:

fieldMappingViewModel.MappedFields():

[
{ "EmailField" : "FirstName", "CrmField" : "FirstName" },
{ "EmailField" : "LastName", "CrmField" : "LastName" },
{ "EmailField" : "Job", "CrmField" : "JobTitle" }...
]

_all:

[
    { "EmailField" : "FirstName", "CrmField" : null },
    { "EmailField" : "LastName", "CrmField" : "LastName" },
    { "EmailField" : "Job", "CrmField" : "JobTitle" }...
    ]

I am trying to create a unique union of these two using:

fieldMappingViewModel.allMappings(_.uniq(_.union(fieldMappingViewModel.MappedFields(), _all),
                function (item, key) {
                    // not the ones that their item.EmailField() already exists with a CrmField value
                }));

Ofcourse the strict equality still leaves in the results objects that have had a repeated Email field but their CrmField is different.

How Can I get rid of the ones with CrmField: Null from my final results? (I only want to filter those null ones that their non-null pair exists. Otherwise I want to keep the pair with null in it)

So I dont end up with

{ "EmailField" : "FirstName", "CrmField" : "FirstName" }

and

{ "EmailField" : "FirstName", "CrmField" : null }

both in the final results. but only:

{ "EmailField" : "FirstName", "CrmField" : "FirstName" }
Ad

Answer

My reasoning is that you need a function that makes:

{ "EmailField" : "FirstName", "CrmField" : "FirstName" }

and

{ "EmailField" : "FirstName", "CrmField" : null }

the same value so a uniq operation will pick only one of them, however depending on which one comes first you can end up with either one of them. In terms of uniq the only other way around is differentiate them and in this case you end up with both which you don't want.

I suggest you use a filter operation that will remove the null values after the uniq.

A possible solution, though probably not the best one due to the extensive use of functions is:

var arr1 = 
    [
    { "EmailField" : "FirstName", "CrmField" : null },
    { "EmailField" : "LastName", "CrmField" : "LastName" },
    { "EmailField" : "Job", "CrmField" : "JobTitle" }
    ];

var arr2 = 
    [
    { "EmailField" : "FirstName", "CrmField" : "FirstName" },
    { "EmailField" : "LastName", "CrmField" : "LastName" },
    { "EmailField" : "Job", "CrmField" : "JobTitle" },
    ];

var res = _.flatten(_.map(_.groupBy(_.union(arr1, arr2), function (item) {
    return item.EmailField;
}), function (set) {
        if (set.length > 1) {
            return _.filter(_.uniq(set, function (item) {
                return item.EmailField + ' ' + item.CrmField;
            }), function (item) {
                return item.CrmField != null;
            });
        }
        return set;        
}));

console.log(res);

The uniq operation is replaced by a groupBy, then we use map and filter to weed out the null values this time taking into account how many instances of this EmailField we have - if there is only one we keep it. Finally we use a flatten to have again a single array of objects.

Ad
source: stackoverflow.com
Ad