Along the same lines as EasyCSP.Core.Array, here's EasyCSP.Core.HashArray

1 view
Skip to first unread message

Bill Farrell

unread,
Jul 7, 2016, 9:33:48 PM7/7/16
to InterSystems: MV Community
This hash-array adds some Python or PHP-like functions to a %ListOfDataTypes. I can't tell you how many times I wish BASIC had a way of referring to known locations in a dynamic array by a name instead of an INCLUDE file (that's just "more code to maintain") or hardwiring constants into your program.

Here's an easier structure: This also gives you the diff and intersect functions, split and join functions, and PHP-like pop function.

class EasyCSP.Core.Array extends %RegisteredObject

Extends %ListOfDataTypes with some Python/Javascript/PHP -like features

Copyright (c) 2011 James W "Bill" Westley-Farrell

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

Apache License 2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

 Inventory


ParametersPropertiesMethodsSystemMethodsQueriesIndicesForeignKeysTriggers
21


 Summary


 Methods


• method Count() as %Integer
Traditional-Cache alias for .length(). This returns the number of elements in the array.
• method Next(key As %Integer = 0) as %Integer
Finds and returns the index value of the element at the location following key in the list. If key is a null string (""), then Next returns the position of the first element in the list (1).
• method append(value As %String = "")
`Add a value to the end of the array
• method clear()
Clear out the array structure
• method diff(compareArray As EasyCSP.Core.Array) as EasyCSP.Core.Array [ Language = mvbasic ]
Returns an array containing all the values that do not exist in both this array and the array passed in. Neither array is changed.
• method dumpAsStream() as %GlobalCharacterStream
Dump the contents of the array in a two-column (key and data) formatted HTML table. Returns a stream that can be output to a web page.
• method find(target As %String = "") as %Integer
Given a string somewhere in the array, return the node where it was found or 0 if not.
• method flip() as EasyCSP.Core.Array
Reverse the order of the values in the array. Returns a new array leaving the original unchanged.
• method get(position) as %String
Retrieve the value from a specific node in the array.
• method intersect(compareArray As EasyCSP.Core.Array) as EasyCSP.Core.Array [ Language = mvbasic ]
Returns an array containing all the values that exist in both this array and the array passed in. Neither array is changed.
• method join(delimiter As %String = ",") as %String [ Language = mvbasic ]
Returns the elements of the array in a delimited string. If a delimiter isn't supplied a comma is used. Any string of any length can be passed in delimiter.
• method length() as %Integer
JQuery/Python-like alias for Count()
• method pop() as %String
Pop a value off the end of the array and shorten the array by one.
• method remove(key As %Integer = 0)
Removes an element and its key completely.
• method set(position As %Integer, value As %String)
Set the value at a specific node in the array. If the position argument is -1, this works the same as .append(). If the position doesn't exist it will be created. If the position has a value, that value will be overwritten.
• method shift() as %String
Shifts a value off the beginning of the array and shortens the array by one. Returns the shifted value. This works the same as PHP array_shift().
• method split(source As %String = "", delimiter As %String = ",") [ Language = mvbasic ]
Split a delimited string into an array. If delimiter is not supplied a comma is assumed. This does not strip spaces around elements in the delimited string. This is useful for splitting comma-delimited strings or dynamic arrays into an array structure. For instance, to compare the contents of a dynamic array with a comma-separated list, split both lists into an EasyCSP.Core.Array then use .intersect() or .diff() to return matches (or non- matches in the case of .diff()).
• method splitList(source As %List = "") [ Language = mvbasic ]
Split a Cache list structure into an array
• method toDynamicArray(quoteStrings As %Boolean = 0) as %String [ Language = mvbasic ]
Returns a string representation of the elements in the array delimited by attribute marks.
• method toJSON() as %String [ Language = mvbasic ]
Returns the elements of the array as JSON.
• method unshift(element As %String) as %Status
Adds a value to the beginning of the array and shifts the original elements up by one.


and the code:

/// Extends %ArrayOfDataTypes with some Python/Javascript/PHP -like features.
/// This structure is similar to a Python dictionary structure.
/// 
/// 
///   <p>Copyright (c) 2011 James W "Bill" Westley-Farrell</p>
/// 
///   <p>Licensed under the Apache License, Version 2.0 (the "License");
///   you may not use this file except in compliance with the License.
///   You may obtain a copy of the License at</p>
/// 
///       <p><a href=http://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a>
/// 
///   <p>Unless required by applicable law or agreed to in writing, software
///   distributed under the License is distributed on an "AS IS" BASIS,
///   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
///   See the License for the specific language governing permissions and
///   limitations under the License.</p>
Class EasyCSP.Core.HashArray Extends %Library.ArrayOfDataTypes
{

/// `Add a value to the end of the array
Method append(
key As %String = "",
value As %String = "")
{
    if $get(key) = "" quit
    set i%Data(key) = value
}

/// Copy items from the source array into this array. Any existing
/// data with the same key will be overwritten.
Method copyFrom(sourceArray As EasyCSP.Core.HashArray)
{
    if $get(sourceArray) '[ "HashArray" quit
    
    set key = sourceArray.Next()
    while key '= "" {
        do ..set(key, sourceArray.get(key))
        set key = sourceArray.Next(key)
    }
}

/// Returns an array containing all the values that do not exist in
/// both this array and the array passed in. Neither array is
/// changed. NOTE: this returns a Core.Array, not a Core.HashArray.
Method diff(compareArray As EasyCSP.Core.HashArray) As EasyCSP.Core.Array [ Language = mvbasic ]
{
    thisDyn = @ME->values()
    thisDynLength = DCount(thisDyn, @fm)
    
    compareDyn = compareArray->values()
    compareDynLength = DCount(compareDyn, @fm)
    
    if thisDynLength >= compareDynLength then
        a = compareDyn
        b = thisDyn
        l = compareDynLength
    end else
        a = thisDyn
        b = compareDyn
        l = thisDynLength
    end
    
    * Use the shorter array to traverse.
    newArray = "EasyCSP.Core.Array"->%New()
    for idx = 1 to l
        find a<idx> in b setting AMC else
            newArray->append(a<idx>)
        end
    next
    
    return newArray
}

/// Dump the contents of the array in a two-column (key and data)
/// formatted HTML table.
Method dumpAsStream() As %GlobalCharacterStream
{
    set stream = ##class(%GlobalCharacterStream).%New()
    
    do stream.WriteLine("<table width=""100%"">")
    
    set idx = ..Next("")
    while idx '= "" {
        set val = ..get(idx)
        do stream.WriteLine("<tr>")
        do stream.WriteLine("<td width=""25%"">"_idx_"</td>")
        do stream.Write("<td>")
        if $isobject(val) {
            do stream.Write("[object]")
        else {
            do stream.Write(val)
        }
        do stream.Write("</td>")
        do stream.WriteLine("</tr>")
        set idx = ..Next(idx)
    }
    
    do stream.WriteLine("</table>")
    
    quit stream
}

/// Returns the value at a specific node in the array. If the key
/// doesn't exist then an empty string is returned.
Method get(key As %String) As %String
{
    quit:$get(key)="" ""
    quit:'..IsDefined(key) ""
    quit i%Data(key)
}

/// Removes a key-value pair from the array and returns
/// the value of the element that was removed. This is
/// like pop()-ing or shift()-ing but from anywhere in
/// the array. If the key-value pair exists, the array
/// is shortened by one after the remove.
Method getAndRemove(key As %String) As %String
{
    quit:$get(key)="" ""
    quit:'..IsDefined(key) ""
    set value = i%Data(key)
    do ..unset(key)
    quit value
}

/// Returns a new array containing all the values that exist in
/// both this array and the array passed in. Neither array is
/// changed. NOTE: This returns a Core.Array, not a Core.HashArray.
Method intersect(compareArray As EasyCSP.Core.HashArray) As EasyCSP.Core.Array [ Language = mvbasic ]
{
    thisDyn = @ME->values()
    thisDynLength = DCount(thisDyn, @fm)
    
    compareDyn = compareArray->values()
    compareDynLength = DCount(compareDyn, @fm)
    
    if thisDynLength >= compareDynLength then
        a = compareDyn
        b = thisDyn
    l = compareDynLength
    end else
        a = thisDyn
        b = compareDyn
        l = thisDynLength
    end
    
    * Use the shorter array to traverse.
    newArray = "EasyCSP.Core.Array"->%New()
    for idx = 1 to l
        find a<idx> in b setting AMC then
            newArray->append(a<idx>)
        end
    next
    
    return newArray
}

/// Wrapper for IsDefined
Method isset(key As %String = "")
{
    quit:$get(key)=""
    quit ..IsDefined(key)
}

/// Return a dynamic array of just the keys in the array. This is
/// the opposite of <method>values</method> which returns just the
/// values in the array.
Method keys() As %String [ Language = mvbasic ]
{
    dynArray = ""
    key = ""
    
    loop 
        key = @ME->Next(key)
    while key <> "" do
        dynArray< -1 > = key
    repeat
    
    return dynArray
}

/// Returns the elements of the array in a delimited string. If
/// a delimiter isn't supplied a comma is used. Any string of
/// any length can be passed in <var>delimiter</var>.
Method join(delimiter As %String = ",") As %String [ Language = mvbasic ]
{
    Dyn = @ME->toDynamicArray
    d = dcount(Dyn, @fm)
    
    rtnDyn = ""
    for idx = 1 to d
        rtnDyn< -1 > = Dyn<idx,2> ; * pick out only the value
    next
    
    rtnDyn = ereplace(rtnDyn, @am, delimiter)
    
    return rtnDyn
}

/// Pop a key-value pair off the end of the array and shorten the
/// array by one. The key-value pair is returned as a single-attribute
/// dynamic array with the key and value separated by a value mark.
Method pop() As %String
{
    set key = $order(i%Data("",-1))
    set value = ..Data(key)
    do ..RemoveAt(key)
    quit key _ $MVVM _ value
}

/// Adds an element or changes the value of an element in the array.
Method set(
key As %String = "",
value As %String = "") As %Status
{
    quit:$get(key)="" $$$ERROR("Key can not be empty.")
    set i%Data(key) = value
    quit $$$OK
}

/// Shifts a value off the beginning of the array and shortens
/// the array by one. Returns the shifted key, a value mark,
/// and the value. Keys are stored sorted naturally by Cache'
/// so this is a pretty quick way of sorting by key.
Method shift() As %String
{
    set key = ..Next("")
    set value = ..GetAt(key)
    do ..RemoveAt(key)
    quit key _ $MVVM _value
}

/// Returns a string representation of the elements in the array
/// delimited by attribute marks. Each attribute contains the
/// original key, a value mark, and the value.
Method toDynamicArray(quoteStrings As %Boolean = 0) As %String [ Language = mvbasic ]
{
    rtnDyn = ""
    
    key = @ME->Next("")
    
    loop while key <> "" do
    
        value = @ME->GetAt(key)
        
        if quoteStrings then
        
            if (oconv(value, "MCN") <> value) then
                value = squote(value)
            end
            
            if value = "" then value = '""'
        end
        
        rtnDyn<-1> = key : @vm : value
        key = @ME->Next(key)
        
    repeat
    
    return rtnDyn
}

/// Returns a string in JSON where each attribute contains two values:
/// key: value
/// 
/// Strings are automatically quoted.
Method toJSON() As %String [ Language = mvbasic ]
{
    nvPairs = @ME->toDynamicArray(1)
    convert @vm:@fm to ":," in nvPairs
    return "{" : nvPairs : "}"
}

/// Remove a name-element pair from the array
Method unset(key As %String = "") As %Status
{
    quit:$get(key)="" $$$ERROR("Key can not be empty.")
    do ..RemoveAt(key)
    quit $$$OK
}

/// Alias for .Clear()
Method unsetAll()
{
    do ..Clear()
}

/// Return a field-mark delimited dynamic array that has
/// just the values in the hash array.
Method values() As %String [ Language = mvbasic ]
{
   
    dynArray = ""
    key = ""
    
    key = @ME->Next("")
    loop while key <> "" do
        dynArray< -1 > = @ME->GetAt(key)
        key = @ME->Next(key)
    repeat
    
    return dynArray
}

Storage Custom
{
<Type>%Library.CompleteCustomStorage</Type>
}

}
Reply all
Reply to author
Forward
0 new messages