создавать вложенные объекты в javascript, например groupby в C#

IList<Customer> Customers =
            flat.GroupBy(cust => new { cust.ReferenceNumber, cust.Name, cust.Address })
                .Select(c => new Customer()
                {
                    ReferenceNumber = c.Key.ReferenceNumber,
                    Name = c.Key.Name,
                    Address = c.Key.Address,
                    Orders = c.Select(o => new Order()
                    {
                        OrderId = o.OrderId,
                        ProductName = o.ProductName,
                        Description = o.Description,
                        Amount = o.Amount
                    }).ToList()
                }).ToList()

Возможно ли в Javascript взять плоский список и преобразовать его во вложенный объект? Общее решение, которое есть??


person Schotime    schedule 26.06.2009    source источник
comment
Легенда! Только что решил мой вопрос о группировке с помощью underscore.js [10022156][1] [1]: stackoverflow.com/questions/10022156/   -  person rickysullivan    schedule 16.04.2012


Ответы (2)


Да.

Вы можете передавать функции в JavaScript, которые служат той же цели, что и лямбда-выражения в коде C#. Возьмем в качестве примера использование JQuery "каждый":

$('div.several').each(function() { 
  // Do something with the current div.
});

Вы также можете легко создавать вложенные объекты:

var outer = {
    inner1: {
        val1: 'a',
        val2: 'b'
    },
    inner2: {
        val1: 'c',
        val2: 'd'
    }
};

Конечно, вы можете сделать это динамически, а не все сразу:

var outer = {};
outer.inner1 = {};
outer.inner1.val1 = 'a';
...

Затем, чтобы сделать то, что вы ищете, вам нужно будет использовать массивы:

var result = [];
for (var i=0; i<x; ++i) {
  result[result.length] = GetIndividualResult(i);
}
person John Fisher    schedule 26.06.2009
comment
Не совсем то, что мне нужно, но некоторые строительные блоки для решения. Ваше здоровье. - person Schotime; 30.06.2009

Несмотря на то, что это старый вопрос, я решил предложить более элегантное решение:

/**
 * Groups an array of objects by one or more keys
 * 
 * @param array arr       The array of objects to group
 * 
 * @param string|function A string representing the child property to group by
 *                        or a function that returns an array of one or more properties.
 * 
 * @returns               An object with keys representing the grouping properties, 
 *                        finally holding an array of records that fell into 
 *                        those groups.
 */
var group = function( items, by ) {
    var groups = {},
        group,
        values,
        i = items.length,
        j,
        key,
        group_keys;

    // make sure we specified how we want it grouped
    if( !by ) { return items; }
    while( i-- ) { 

        // find out group values for this item
        values = ( typeof(by) === "function" && by( items[i] ) || 
                   typeof items[i] === "object" && items[i][by] || 
                   items[i] );

        // make sure our group values are an array
        values = values instanceof Array && values || [ values ];

        // recursively group
        group = groups;
        for( j = 0; j < values.length; j++ ) {
            key = values[j];
            group = ( group [key] || ( group [key] = j === values.length - 1 && [] || {} ) );
        }

        // for the last group, push the actual item onto the array
        group = ( group instanceof Array && group || [] ).push( items[i] );
    }

    return groups;
};

Вызов с этим:

var items = [
    { "id" : 1, "name" : "foo",  "category" : "a" },
    { "id" : 2, "name" : "foo",  "category" : "a" },
    { "id" : 3, "name" : "bar",  "category" : "b" },
    { "id" : 4, "name" : "free", "category" : "a" },
    { "id" : 5, "name" : "beer", "category" : "b" },
    { "id" : 6, "name" : "foo",  "category" : "b" }
];

var groups = group( items, function( item ) { return [ item.category, item.name ]; } );

Выдает это:

{
    b: {
        foo: [
            {
                id: 6
                name: foo
                category: b
            }
        ]
        beer: [
            {
                id: 5
                name: beer
                category: b
            }
        ]
        bar: [
            {
                id: 3
                name: bar
                category: b
            }
        ]
    }
    a: {
        free: [
            {
                id: 4
                name: free
                category: a
            }
        ]
        foo: [
            {
                id: 2
                name: foo
                category: a
            }
            {
                id: 1
                name: foo
                category: a
            }
        ]
    }
}

В любом случае, надеюсь, что это кому-то поможет.

person Jason T Featheringham    schedule 10.07.2011
comment
+1 за сценарий! Я пытался реализовать это самостоятельно, но безуспешно: P ... это слишком загадочно, на мой взгляд, но это работает, в любом случае я заменил элементы на arr, чтобы он работал правильно. Спасибо ;) - person daveoncode; 03.08.2011
comment
Добро пожаловать! Да, загадочная природа этой функции допускает вложенную группировку (например, группировка по категории, а затем по имени). Рекурсия — наш друг, и она упрощает эту задачу. - person Jason T Featheringham; 12.11.2011
comment
Превосходно! И легко сделать как плагин jquery, спасибо! Я сделал исправление arr/items к вашему ответу, теперь все должно быть в порядке. - person Jerther; 09.01.2015
comment
Спасибо за помощь @Jerther - person Jason T Featheringham; 17.02.2015
comment
Я подумал, что могу предложить более элегантное решение -- или, ну, решение. Потому что принятый ответ совсем не один. - person John Weisz; 25.01.2017