Wiki

Ticket #150 (new enhancement)

Opened 9 years ago

Last modified 9 years ago

Implement extend IList<of T>.toDictionary<of TKey>(...)

Reported by: Chuck Owned by:
Priority: major Milestone:
Component: Cobra Compiler Version: 0.8.0
Keywords: dictionary, extension Cc:

Description

Suppose you have a list of customers. You may wish to convert the list to a dictionary keyed by customer name (or customer code).

Likewise with an enumerable.

Would be nice to do it via one expression as enable by an extension method:

byName = customers.toDictionary<of String>(do(c as Customer)=c.name))
# perhaps with inference it could be shortened to:
byName = customers.toDictionary(do(c as Customer)=c.name))

# for now you can do this
byName = Dictionary<of String, Customer>()
for c in customers, byName[c.name] = c

There are various issues to work out to accomplish this as expressed in the TODO's below. This ticket is possibly more interesting for those issues than for the actual extension method.

# x-to-dictionary.cobra
# in Workspace-new

sig Transform(input) as dynamic
        
namespace Cobra.Lang

    extend IList<of T>

/#      
        # TODO: support generic delegate declaration
            
        sig KeyFor<of TIn, TOut>(value as TIn) as TOut

        def toDictionary<of TKey>(keyFor as KeyFor<of T, TKey>) as Dictionary<of TKey, T>
            d = Dictionary<of TKey, T>()
            for item in this
                key = keyFor(item)
                d[key] = item
            return d
#/

/#
        # TODO: No Func before .NET 3.5. Would be nice if Cobra std lib filled it in
        
        def toDictionary<of TKey>(keyFor as Func<of T, TKey>) as Dictionary<of TKey, T>
            d = Dictionary<of TKey, T>()
            for item in this
                key = keyFor(item)
                d[key] = item
            return d
#/

        # TODO: can't do generic methods in generic extensions yet
        
        def toDictionary<of TKey>(keyFor as Transform) as Dictionary<of TKey, T>
            ensure
                result.count == .count
            body
                d = Dictionary<of TKey, T>()
                for item in this
                    key = keyFor(item)
                    d[key] = item
                return d


class TestCustomer

    def init(name as String, balance as decimal)
        _name, _balance = name, balance

    get name from var as String
    
    get balance from var as decimal


class Test

    test
        customers = [
            TestCustomer('Acme, Inc.', 15_400.00),
            TestCustomer('Systems LLC', 6_800.00),
        ]
        d = customers.toDictionary<of String>(do(c as Customer))
            return c.name
        assert d.count == 2
        assert d['Acme, Inc.'].balance == 15_400.00
        assert d['Systems LLC'].balance == 6_800.00
        print 'done testing.'

    def main is shared
        print 'done main.'

The file in question where this would land is <workspace>\Source\Cobra.Lang\ExtendList.cobra and ExtendEnumerable.cobra.

Change History

Changed 9 years ago by jonathandavid

I agree that the TO-DOs above are important on themselves.

The functionality of toDictionary can be achieved too if we implement a method that behaves like Python's zip:

byName = Collections.zip(customers, for c in customers get c.name)

Note: See TracTickets for help on using tickets.