Carlos Martinez T
Carlos Martinez T

Reputation: 6528

Joins and Aggregates in Javascript Arrays

I have been trying for hours to do this using json.js but is just too much for something that seems simple. I have this example data:

    var hotels = [
        { id: 101, Name: "Hotel 101", WebFacilities: [8, 9, 10] },
        { id: 102, Name: "Hotel 101", WebFacilities: [8] },
        { id: 103, Name: "Hotel 101", WebFacilities: [8, 10] }
    ];

    var facilities = [
        { id: 8, Name: "Facility 8" },
        { id: 9, Name: "Facility 9" },
        { id: 10, Name: "Facility 10" }
    ];

I want to get this:

    var selectedFacilities = [
        { id: 8, Name: "Facility 8", Count: 3 },
        { id: 9, Name: "Facility 9", Count: 1 },
        { id: 10, Name: "Facility 10", Count: 2 }
    ];

How do I do this?

Upvotes: 0

Views: 2291

Answers (2)

Jeff Mercado
Jeff Mercado

Reputation: 134841

So it appears you're trying to count how many of each facility there is.

Here's one way to write the query using C#:

var hotelFacilities =
    from hotel in hotels
    from id in hotel.WebFacilities
    group id by id;

var query =
    from facility in facilities
    join g in hotelFacilities on facility.id equals g.Key
    select new
    {
        id = facility.id,
        Name = facility.Name,
        Count = g.Count(),
    };

Now if you can picture this using the method syntax, it is almost a 1:1 transformation to the linq.js version.

Note the way the compiler translates the above will usually include the GroupBy() call within the previous SelectMany() call. However written this way will make writing the linq.js equivalent query easier and less awkward.

var hotelFacilities = hotels
    .SelectMany(hotel => hotel.WebFacilities)
    .GroupBy(id => id);

var query = facilities
    .Join(
        hotelFacilities,
        facility => facility.id,
        g => g.Key,
        (facility, g) => new
        {
            id = facility.id,
            Name = facility.Name,
            Count = g.Count(),
        }
    );

And the equivalent linq.js query.

var hotelFacilities = Enumerable.From(hotels)
    .SelectMany("hotel => hotel.WebFacilities")
    .GroupBy("id => id")
    .ToArray();

var query = Enumerable.From(facilities)
    .Join(
        hotelFacilities,
        "facility => facility.id",
        "g => g.Key()",
        "(facility, g) => { id: facility.id, Name: facility.Name, Count: g.Count() }"
    ).ToArray();

Upvotes: 2

ATOzTOA
ATOzTOA

Reputation: 35950

Use this:

var selectedFacilities = facilities;

for(var i = 0; i < facilities.length; i++) {
    for(var j = 0; j < hotels.length; j++) {
        if(hotels[j]["id"] == facilities[i]["id"]) {
            // Add data
            selectedFacilities[i]["Count"] = hotels[i]["WebFacilities"].length;
        } else {
            selectedFacilities[i]["Count"] = 0;
        }
    }

}

Upvotes: 0

Related Questions