Douglas Gaskell
Douglas Gaskell

Reputation: 10030

Linq JS join syntax

I am trying to join an array of dates and values to an array of dates, without filtering out the extra dates. The LinqJS reference here is pretty confusing on how I would actually go about using the join. The question here did not help much either.

Edit:

Join documentation here: https://svschmidt.github.io/linqjs/Collection.html#Join

It looks like I need help sorting out how to get the join to be an outer and not an inner join so it includes null/undefined values.

Say I have two arrays:

Array 1:

[
'2017-02-10',
'2017-02-11',
'2017-02-12',
'2017-02-13',
'2017-02-20',
'2017-02-21',
'2017-02-22',
'2017-02-23',
'2017-02-24',
'2017-02-25',
'2017-02-26',
'2017-02-27'
]

Array 2:

[
  { date: '2017-02-10', value:  5 },
  { date: '2017-02-12', value:  8 },
  { date: '2017-02-13', value: 13 },
  { date: '2017-02-21', value: 14 },
  { date: '2017-02-24', value: 11 },
  { date: '2017-02-27', value:  7 }
]

I want to join them so I get this as my result (- for undefined):

[
'5',
-,
'8',
'13',
-,
'14',
-,
-,
'11',
-,
-,
'7'
]

My current syntax:

Enumerable.from(array1).join(array2, '$', '$.date', "outer, inner => inner.value").toArray()

This results in an array of the values, but the results are still inner joined, and it filters out what might be the null/undefined items.

How can I do this? How does the join syntax work for LinqJS?

Upvotes: 3

Views: 4956

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386620

You could use GroupJoin

Correlates the elements of two sequences based on equality of keys and groups the results. The default equality comparer is used to compare keys.

for a LEFT OUTER JOIN and specify the wanted value and use DefaultIfEmpty

Returns the elements of the specified sequence or the specified value in a singleton collection if the sequence is empty.

with the wanted replacement, if null.

var dates = ['2017-02-10', '2017-02-11', '2017-02-12', '2017-02-13', '2017-02-20', '2017-02-21', '2017-02-22', '2017-02-23', '2017-02-24', '2017-02-25', '2017-02-26', '2017-02-27'],
    values = [{ date: '2017-02-10', value: 5 }, { date: '2017-02-12', value: 8 }, { date: '2017-02-13', value: 13 }, { date: '2017-02-21', value: 14 }, { date: '2017-02-24', value: 11 }, { date: '2017-02-27', value: 7 }],
    result = Enumerable
        .From(dates)
        .GroupJoin(
            values,
           '',
           '$.date',
           't, u => ({ date: t, value: u.Select("$.value").DefaultIfEmpty("-").ToString() })')
        .ToArray();

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>

ES6

var dates = ['2017-02-10', '2017-02-11', '2017-02-12', '2017-02-13', '2017-02-20', '2017-02-21', '2017-02-22', '2017-02-23', '2017-02-24', '2017-02-25', '2017-02-26', '2017-02-27'],
    values = [{ date: '2017-02-10', value: 5 }, { date: '2017-02-12', value: 8 }, { date: '2017-02-13', value: 13 }, { date: '2017-02-21', value: 14 }, { date: '2017-02-24', value: 11 }, { date: '2017-02-27', value: 7 }],
    result = Enumerable
        .From(dates)
        .GroupJoin(
            values,
            '',
            '$.date',
            (t, u) => ({
               date: t,
               value: u.Select("$.value").DefaultIfEmpty("-").ToString()
            }))
        .ToArray();

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>

Upvotes: 3

samanime
samanime

Reputation: 26557

I'm not sure about LinqJS, but regular JS is more than capable of doing this.

There are a couple ways to go about it. The reduce(), map(), and sort() functions are very Linq-esque and work well natively. (There is also filter() and a number of others).

const dates = [
'2017-02-10',
'2017-02-11',
'2017-02-12',
'2017-02-13',
'2017-02-20',
'2017-02-21',
'2017-02-22',
'2017-02-23',
'2017-02-24',
'2017-02-25',
'2017-02-26',
'2017-02-27'
]

const data = [
  { date: '2017-02-10', value:  5 },
  { date: '2017-02-12', value:  8 },
  { date: '2017-02-13', value: 13 },
  { date: '2017-02-21', value: 14 },
  { date: '2017-02-24', value: 11 },
  { date: '2017-02-27', value:  7 }
];

const result = dates
  .map(date => ({ date, value: '-' }))
  .concat(data)
  .filter(({ date, value }) => !(data.find(d => d.date === date) && value === '-'))
  .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());

console.log(result);

const justValues = Object.keys(result).map(key => result[key].value);

console.log(justValues);

Upvotes: 5

Related Questions