Correctly depends on intended use.
If you're really going to use this one item at a time, you can greatly
increase average performance of deletes by deferring them for later
(for example). Similarly, you can avoid some overhead by implementing
that as an object.
That said, here's a more concise implementation:
emptyHash=: i.2 0
canonical=: boxopen
hashSet=:1 :0
:
j=. ({.y) i. x=. canonical x
n=.-.o=. j<{:$y
(({.y),n#x),:((o#m) (o#j)} {:y),n#m=. canonical m
)
hashGet=:4 :0
j=. ({.y) i. canonical x
b=. +./j={:$y
j { ({:y),b#<'not found'
)
hashDel=:4 :0
(-.({.y) e. canonical x) #"1 y
)
test=: emptyHash
test1=: 'a' 13 hashSet test
test2=: 'a' 'Aye' hashSet test1
test3=: 'bb' 17 hashSet test2
test4=: 'bb' hashDel test3
test
test1
┌──┐
│a │
├──┤
│13│
└──┘
test2
┌───┐
│a │
├───┤
│Aye│
└───┘
test3
┌───┬──┐
│a │bb│
├───┼──┤
│Aye│17│
└───┴──┘
('a';'bb') hashGet test3
┌───┬──┐
│Aye│17│
└───┴──┘
('bb';'a') hashGet test4
┌─────────┬───┐
│not found│Aye│
└─────────┴───┘
As you can see, I made a few changes to your interface. If you're not
going to support setting and selecting multiple values, you should
think about using variables instead.
On the other hand, if there's actual values to forming lists of these
things, leaving things boxed might make sense.
Or, if there's real reasons why neither of these options fit your use
case, we should have that use case expressed explicitly because it's
going to matter.
Thanks,
--
Raul
On Mon, Dec 4, 2017 at 11:29 AM, Andrew Dabrowski <[email protected]> wrote:
> Here's my solution. Not doubt it is ugly and slow. I look forward to you
> guys showing me how to do it correctly.
>
> emptyHash =: ,~ ,. < 'not found'
>
> hashSet =: dyad define
> 'key val' =. y
> pos =. x hashGetInd key
> if. pos = 1{ $x
> do. x ,"(1,0) key ; val
> else. ((< key) pos} (0{x)) ,: (< val) pos} (1{x)
> end.
> )
>
> hashGetInd =: dyad define
> keylist =. > 0{ x
> len =. # 0{ keylist
> if. len > #y
> do. key =. y , ((len - #y) # ' ')
> else. key =. len {. y
> end.
> keylist i. key
> )
>
> hashGet =: dyad define
> pos =. x hashGetInd y
> if. pos = 1{ $x
> do. > 0 { 1{ x
> else. > pos { 1{ x
> end.
> )
>
> hashDel =: dyad define
> pos =. x hashGetInd y
> if. pos < 1{ $x
> do. (<<< pos) {"1 x
> end.
> )
>
> Example:
>
> test =: emptyHash
> test
> ┌─────────┐
> │not found│
> ├─────────┤
> │not found│
> └─────────┘
> test1 =: test hashSet 'a' ; 13
> test1
> ┌─────────┬──┐
> │not found│a │
> ├─────────┼──┤
> │not found│13│
> └─────────┴──┘
> test2 =: test1 hashSet 'a' ; 'Aye'
> test2
> ┌─────────┬───┐
> │not found│a │
> ├─────────┼───┤
> │not found│Aye│
> └─────────┴───┘
> test3 =: test2 hashSet 'bb' ; 17
> test3
> ┌─────────┬───┬──┐
> │not found│a │bb│
> ├─────────┼───┼──┤
> │not found│Aye│17│
> └─────────┴───┴──┘
> test3 hashGet 'a'
> Aye
> test3 hashGet 'bb'
> 17
> test4 =: test3 hashDel 'bb'
> test4
> ┌─────────┬───┐
> │not found│a │
> ├─────────┼───┤
> │not found│Aye│
> └─────────┴───┘
> test4 hashGet 'bb'
> not found
> test4 hashGet 'a'
> Aye
>
>
> On 12/03/2017 04:25 PM, Henry Rich wrote:
>>
>> Perhaps we shouldn't try to make a full datatype for associative arrays,
>> but just a set of functions (foreigns, or (m h.) ) that do what's needed.
>>
>> We would need to decide what's needed.
>>
>> hashtable =: keys create values
>> indexes =: hashtable lookup keys (like i.)
>> values =: hashtable fetch indexes (like {)
>> hashtable =: hashtable add keys;values
>> hashtable =: hashtable delete indexes
>>
>> That would not be the hardest thing to implement; perhaps we should start
>> a strawman in Interpreter/Requests.
>
>
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm