This is an automated email from the ASF dual-hosted git repository.

kevingurney pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new e14f60b7ef GH-38398: [MATLAB] Improve array display (#38400)
e14f60b7ef is described below

commit e14f60b7efd2d41c6ede8569ac1a8b07da3cbf73
Author: sgilmore10 <[email protected]>
AuthorDate: Tue Oct 24 13:42:41 2023 -0400

    GH-38398: [MATLAB] Improve array display (#38400)
    
    
    
    ### Rationale for this change
    
    Currently, the display for `arrow.array.Array`s is not very MATLAB-like:
    
    ```matlab
    
    >> a = arrow.array([1 2 3 4])
    
    a =
    
    [
      1,
      2,
      3,
    ]
    ```
    
    At the very least, the display should include the class header and indent 
each line by 4 spaces. Here's one display option:
    
    ```matlab
    
    >> a = arrow.array([1 2 3 4])
    
    a =
    
      Float64Array with 4 elements and 0 null values:
    
        1 | 2 | 3 | 4
    
    ```
    
    ### What changes are included in this PR?
    
    1. Array display now includes a class header, which states the array type 
and the number of elements/nulls in the array.
    2. Changed the 
[`window`](https://github.com/apache/arrow/blob/37935604bf168a3b2d52f3cc5b0edf83b5783309/cpp/src/arrow/pretty_print.h#L79C1-L80C1)
 size to 3 from 10.
    3. Primitive and string arrays are displayed horizontally, i.e. set 
[`skip_new_lines`](https://github.com/apache/arrow/blob/37935604bf168a3b2d52f3cc5b0edf83b5783309/cpp/src/arrow/pretty_print.h#L90)
 to `false`. Uses ` | ` as the delimiter between elements with no 
opening/closing brackets.
    4. All other array types (`struct`, `list`, etc) are displayed vertically 
with an `indent` of 4.
    
    **Example String Array Display:**
    
    ```matlab
    >> a = arrow.array(["Hello", missing, "Bye"])
    
    a =
    
      StringArray with 3 elements and 1 null value:
    
        "Hello" | null | "Bye"
    ```
    
    **Example Struct Array Display:**
    
    ```matlab
    
    >>  a1 = arrow.array(["Hello", missing, "Bye"]);
    >> a2 = arrow.array([1 2 3]);
    >> structArray = arrow.array.StructArray.fromArrays(a1, a2)
    
    structArray =
    
      StructArray with 3 elements and 0 null values:
    
            -- is_valid: all not null
        -- child 0 type: string
            [
                "Hello",
                null,
                "Bye"
            ]
        -- child 1 type: double
            [
                1,
                2,
                3
            ]
    ```
    
    ### Are these changes tested?
    
    Yes. Added a new test class called `tArrayDisplay.m` with unit tests for 
array display.
    
    ### Are there any user-facing changes?
    
    Yes. Users will see a different display for arrays now.
    
    ### Future Directions
    
    1. #38166
    * Closes: #38398
    
    Lead-authored-by: Sarah Gilmore <[email protected]>
    Co-authored-by: sgilmore10 <[email protected]>
    Co-authored-by: Sutou Kouhei <[email protected]>
    Signed-off-by: Kevin Gurney <[email protected]>
---
 matlab/src/cpp/arrow/matlab/array/proxy/array.cc   |  30 +-
 matlab/src/cpp/arrow/matlab/error/error.h          |   1 +
 .../+arrow/+array/+internal/+display/getHeader.m   |  38 +++
 .../+internal/+display/pluralizeStringIfNeeded.m   |  23 ++
 matlab/src/matlab/+arrow/+array/Array.m            |  16 +-
 matlab/test/arrow/array/tArrayDisplay.m            | 334 +++++++++++++++++++++
 6 files changed, 439 insertions(+), 3 deletions(-)

diff --git a/matlab/src/cpp/arrow/matlab/array/proxy/array.cc 
b/matlab/src/cpp/arrow/matlab/array/proxy/array.cc
index bd8e9dc842..4e52c990d3 100644
--- a/matlab/src/cpp/arrow/matlab/array/proxy/array.cc
+++ b/matlab/src/cpp/arrow/matlab/array/proxy/array.cc
@@ -21,10 +21,13 @@
 #include "arrow/matlab/bit/unpack.h"
 #include "arrow/matlab/error/error.h"
 #include "arrow/matlab/type/proxy/wrap.h"
+#include "arrow/pretty_print.h"
 #include "arrow/type_traits.h"
 
 #include "libmexclass/proxy/ProxyManager.h"
 
+#include <sstream>
+
 namespace arrow::matlab::array::proxy {
 
     Array::Array(std::shared_ptr<arrow::Array> array) : 
array{std::move(array)} {
@@ -44,7 +47,32 @@ namespace arrow::matlab::array::proxy {
 
     void Array::toString(libmexclass::proxy::method::Context& context) {
         ::matlab::data::ArrayFactory factory;
-        const auto str_utf8 = array->ToString();
+        
+        auto opts = arrow::PrettyPrintOptions::Defaults();
+        opts.window = 3;
+        opts.indent = 4;
+        opts.indent_size = 4;
+
+        const auto type_id = array->type()->id();
+        if (arrow::is_primitive(type_id) || arrow::is_string(type_id)) {
+            /* 
+             * Display primitive and string types horizontally without 
+             * opening and closing delimiters. Use " | " as the delimiter
+             * between elments. Below is an example Int32Array display:
+             *
+             *    1 | 2 | 3 | ... | 6 | 7 | 8
+             */
+            opts.skip_new_lines = true;
+            opts.array_delimiters.open = "";
+            opts.array_delimiters.close = "";
+            opts.array_delimiters.element = " | ";
+        }
+
+        std::stringstream ss;
+        MATLAB_ERROR_IF_NOT_OK_WITH_CONTEXT(arrow::PrettyPrint(*array, opts, 
&ss), context, error::ARRAY_PRETTY_PRINT_FAILED);
+        
+        const auto str_utf8 = opts.skip_new_lines ? "    " + ss.str() : 
ss.str();
+
         MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(const auto str_utf16, 
arrow::util::UTF8StringToUTF16(str_utf8), context, 
error::UNICODE_CONVERSION_ERROR_ID);
         auto str_mda = factory.createScalar(str_utf16);
         context.outputs[0] = str_mda;
diff --git a/matlab/src/cpp/arrow/matlab/error/error.h 
b/matlab/src/cpp/arrow/matlab/error/error.h
index a512fdcc89..2d8f5c432c 100644
--- a/matlab/src/cpp/arrow/matlab/error/error.h
+++ b/matlab/src/cpp/arrow/matlab/error/error.h
@@ -201,4 +201,5 @@ namespace arrow::matlab::error {
     static const char* INDEX_EMPTY_CONTAINER = "arrow:index:EmptyContainer";
     static const char* INDEX_OUT_OF_RANGE = "arrow:index:OutOfRange";
     static const char* BUFFER_VIEW_OR_COPY_FAILED = 
"arrow:buffer:ViewOrCopyFailed";
+    static const char* ARRAY_PRETTY_PRINT_FAILED = 
"arrow:array:PrettyPrintFailed";
 }
diff --git a/matlab/src/matlab/+arrow/+array/+internal/+display/getHeader.m 
b/matlab/src/matlab/+arrow/+array/+internal/+display/getHeader.m
new file mode 100644
index 0000000000..5c8704d5bf
--- /dev/null
+++ b/matlab/src/matlab/+arrow/+array/+internal/+display/getHeader.m
@@ -0,0 +1,38 @@
+%GETHEADER Generates the display header for arrow.array.Array classes
+
+% Licensed to the Apache Software Foundation (ASF) under one or more
+% contributor license agreements.  See the NOTICE file distributed with
+% this work for additional information regarding copyright ownership.
+% The ASF licenses this file to you 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
+%
+%   http://www.apache.org/licenses/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.
+
+function header = getHeader(className, numElements, numNulls)
+    import arrow.array.internal.display.pluralizeStringIfNeeded
+    elementString = pluralizeStringIfNeeded(numElements, "element");
+
+    nullString = pluralizeStringIfNeeded(numNulls, "null value");
+    
+    numString = "%d";
+    if usejava("desktop")
+        % Bold the number of elements and nulls if the desktop is enabled
+        numString = compose("<strong>%s</strong>", numString);
+    end
+
+    formatSpec = "  %s with " + numString + " %s and " + numString + " %s";
+    if numElements > 0
+        formatSpec = formatSpec + ":";
+    end
+    formatSpec = formatSpec + newline;
+    
+    header = compose(formatSpec, className, numElements, elementString, 
numNulls, nullString);
+    header = char(header);
+end
\ No newline at end of file
diff --git 
a/matlab/src/matlab/+arrow/+array/+internal/+display/pluralizeStringIfNeeded.m 
b/matlab/src/matlab/+arrow/+array/+internal/+display/pluralizeStringIfNeeded.m
new file mode 100644
index 0000000000..ae9eafba92
--- /dev/null
+++ 
b/matlab/src/matlab/+arrow/+array/+internal/+display/pluralizeStringIfNeeded.m
@@ -0,0 +1,23 @@
+%PLURALIZESTRINGIFNEEDED Pluralizes str if num is not equal to 1.
+
+% Licensed to the Apache Software Foundation (ASF) under one or more
+% contributor license agreements.  See the NOTICE file distributed with
+% this work for additional information regarding copyright ownership.
+% The ASF licenses this file to you 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
+%
+%   http://www.apache.org/licenses/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.
+
+function str = pluralizeStringIfNeeded(num, str)
+    if num ~= 1
+        str = str + "s";
+    end
+end
+
diff --git a/matlab/src/matlab/+arrow/+array/Array.m 
b/matlab/src/matlab/+arrow/+array/Array.m
index 381e734983..293ad87ad4 100644
--- a/matlab/src/matlab/+arrow/+array/Array.m
+++ b/matlab/src/matlab/+arrow/+array/Array.m
@@ -62,8 +62,21 @@ classdef (Abstract) Array < matlab.mixin.CustomDisplay & ...
     end
 
     methods (Access=protected)
+        function header = getHeader(obj)
+            name = matlab.mixin.CustomDisplay.getClassNameForHeader(obj);
+            numElements = obj.NumElements;
+            % TODO: Add NumValid and NumNull as properties to Array to
+            % avoid materializing the Valid property. This will improve
+            % performance for large arrays.
+            numNulls = nnz(~obj.Valid);
+            header = arrow.array.internal.display.getHeader(name, numElements, 
numNulls);
+        end
+
         function displayScalarObject(obj)
-            disp(obj.toString());
+            disp(getHeader(obj));
+            if obj.NumElements > 0
+                disp(toString(obj) + newline);
+            end
         end
     end
 
@@ -86,4 +99,3 @@ classdef (Abstract) Array < matlab.mixin.CustomDisplay & ...
         end
     end
 end
-
diff --git a/matlab/test/arrow/array/tArrayDisplay.m 
b/matlab/test/arrow/array/tArrayDisplay.m
new file mode 100644
index 0000000000..578f5fe82a
--- /dev/null
+++ b/matlab/test/arrow/array/tArrayDisplay.m
@@ -0,0 +1,334 @@
+%TARRAYDISPLAY Unit tests for array display.
+
+classdef tArrayDisplay < matlab.unittest.TestCase
+% Licensed to the Apache Software Foundation (ASF) under one or more
+% contributor license agreements.  See the NOTICE file distributed with
+% this work for additional information regarding copyright ownership.
+% The ASF licenses this file to you 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
+%
+%   http://www.apache.org/licenses/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.
+
+    properties (TestParameter)
+        EmptyArray
+        ArrayWithOneElement
+        ArrayWithMultipleElements
+        ArrayWithOneNull
+        ArrayWithMultipleNulls
+    end
+
+    methods(TestParameterDefinition, Static)
+        function EmptyArray = initializeEmptyArray()
+            EmptyArray.Boolean = arrow.array(logical.empty(0, 0));
+            EmptyArray.UInt8 = arrow.array(uint8.empty(0, 0));
+            EmptyArray.Int64 = arrow.array(int64.empty(0, 0));
+            EmptyArray.Time64 = arrow.array(duration.empty(0, 0));
+            EmptyArray.Timestamp = arrow.array(datetime.empty(0, 0));
+            EmptyArray.String = arrow.array(string.empty(0, 0));
+        end
+
+        function ArrayWithOneElement = initializeArrayWithOneElement()
+            boolStruct = struct(Array=arrow.array(true), String="true");
+            ArrayWithOneElement.Boolean = boolStruct;
+            
+            uint8Struct = struct(Array=arrow.array(uint8(1)), String="1");
+            ArrayWithOneElement.UInt8 = uint8Struct; 
+
+            int64Struct = struct(Array=arrow.array(int64(2)), String="2");
+            ArrayWithOneElement.Int64 = int64Struct;
+
+            time64Struct = struct(Array=arrow.array(seconds(1)), 
String="00:00:01.000000");
+            ArrayWithOneElement.Time64 = time64Struct; 
+
+            timestampStruct = struct(Array=arrow.array(datetime(2023, 10, 20), 
TimeUnit="Second"), String="2023-10-20 00:00:00");
+            ArrayWithOneElement.Timestamp = timestampStruct;
+
+            stringStruct = struct(Array=arrow.array("A"), String="""A""");
+            ArrayWithOneElement.String = stringStruct;
+        end
+
+        function ArrayWithMultipleElements = 
initializeArrayWithMultipleElements()
+            boolStruct = struct(Array=arrow.array([true false true]), ...
+                String="true | false | true");
+            ArrayWithMultipleElements.Boolean = boolStruct;
+            
+            uint8Struct = struct(Array=arrow.array(uint8([1 10 100])), ...
+                String="1 | 10 | 100");
+            ArrayWithMultipleElements.UInt8 = uint8Struct; 
+
+            int64Struct = struct(Array=arrow.array(int64([2 1 20])), ...
+                String="2 | 1 | 20");
+            ArrayWithMultipleElements.Int64 = int64Struct;
+
+            time64Struct = struct(Array=arrow.array(seconds([1 2 3])), ...
+                String="00:00:01.000000 | 00:00:02.000000 | 00:00:03.000000");
+            ArrayWithMultipleElements.Time64 = time64Struct; 
+
+            timestampStruct = struct(Array=arrow.array(datetime(2023, 10, 20) 
+ days(0:2) , TimeUnit="Second"), ...
+                String="2023-10-20 00:00:00 | 2023-10-21 00:00:00 | 2023-10-22 
00:00:00");
+            ArrayWithMultipleElements.Timestamp = timestampStruct;
+
+            stringStruct = struct(Array=arrow.array(["A" "ABC" "ABCDE"]), ...
+                String="""A"" | ""ABC"" | ""ABCDE""");
+            ArrayWithMultipleElements.String = stringStruct;
+        end
+
+        function ArrayWithOneNull = initializeArrayWithOneNull()
+            boolStruct = struct(Array=arrow.array([true false true], Valid=[1 
3]), ...
+                String="true | null | true");
+            ArrayWithOneNull.Boolean = boolStruct;
+            
+            uint8Struct = struct(Array=arrow.array(uint8([1 10 100]), Valid=[2 
3]), ...
+                String="null | 10 | 100");
+            ArrayWithOneNull.UInt8 = uint8Struct; 
+
+            int64Struct = struct(Array=arrow.array(int64([2 1 20]), Valid=[1 
2]), ...
+                String="2 | 1 | null");
+            ArrayWithOneNull.Int64 = int64Struct;
+
+            time64Struct = struct(Array=arrow.array(seconds([1 NaN 3])), ...
+                String="00:00:01.000000 | null | 00:00:03.000000");
+            ArrayWithOneNull.Time64 = time64Struct; 
+
+            timestampStruct = struct(Array=arrow.array([datetime(2023, 10, 20) 
+ days(0:1) NaT] , TimeUnit="Second"), ...
+                String="2023-10-20 00:00:00 | 2023-10-21 00:00:00 | null");
+            ArrayWithOneNull.Timestamp = timestampStruct;
+
+            stringStruct = struct(Array=arrow.array([missing "ABC" "ABCDE"]), 
...
+                String="null | ""ABC"" | ""ABCDE""");
+            ArrayWithOneNull.String = stringStruct;
+        end
+
+        function ArrayWithMultipleNulls = initializeArrayWithMultipleNulls()
+            boolStruct = struct(Array=arrow.array([true false true], Valid=1), 
...
+                String="true | null | null");
+            ArrayWithMultipleNulls.Boolean = boolStruct;
+            
+            uint8Struct = struct(Array=arrow.array(uint8([1 10 100]), 
Valid=2), ...
+                String="null | 10 | null");
+            ArrayWithMultipleNulls.UInt8 = uint8Struct; 
+
+            int64Struct = struct(Array=arrow.array(int64([2 1 20]), Valid=3), 
...
+                String="null | null | 20");
+            ArrayWithMultipleNulls.Int64 = int64Struct;
+
+            time64Struct = struct(Array=arrow.array(seconds([1 NaN NaN])), ...
+                String="00:00:01.000000 | null | null");
+            ArrayWithMultipleNulls.Time64 = time64Struct; 
+
+            timestampStruct = struct(Array=arrow.array([datetime(2023, 10, 20) 
NaT NaT] , TimeUnit="Second"), ...
+                String="2023-10-20 00:00:00 | null | null");
+            ArrayWithMultipleNulls.Timestamp = timestampStruct;
+
+            stringStruct = struct(Array=arrow.array([missing "ABC" missing]), 
...
+                String="null | ""ABC"" | null");
+            ArrayWithMultipleNulls.String = stringStruct;
+        end
+    end
+
+    methods (Test)
+
+        function DisplayEmptyArray(testCase, EmptyArray)
+            import arrow.internal.test.display.makeLinkString
+
+            fullClassName = string(class(EmptyArray)); 
+            displayName = extractAfter(fullClassName, "arrow.array.");
+            classNameLink = makeLinkString(FullClassName=fullClassName, ...
+                                           ClassName=displayName, ...
+                                           BoldFont=true);
+            zeroString = getNumString(0);
+            header = compose("  %s with %s elements and %s null values" + 
newline, ...
+                classNameLink, zeroString, zeroString);
+
+            expectedDisplay = char(header + newline);
+            actualDisplay = evalc('disp(EmptyArray)');
+            testCase.verifyEqual(actualDisplay, expectedDisplay);
+        end
+
+        function DisplayArrayWithOneElement(testCase, ArrayWithOneElement)
+            import arrow.internal.test.display.makeLinkString
+
+            array = ArrayWithOneElement.Array;
+            fullClassName = string(class(array)); 
+            displayName = extractAfter(fullClassName, "arrow.array.");
+            classNameLink = makeLinkString(FullClassName=fullClassName, ...
+                                           ClassName=displayName, ...
+                                           BoldFont=true);
+
+            numElementString = getNumString(1);
+            numNullString = getNumString(0);
+            header = compose("  %s with %s element and %s null values:" + 
newline, ...
+                classNameLink, numElementString, numNullString);
+
+            body = "    " + ArrayWithOneElement.String + newline + newline;
+            expectedDisplay = char(strjoin([header body], newline));
+            actualDisplay = evalc('disp(array)');
+            testCase.verifyEqual(actualDisplay, expectedDisplay);
+        end
+
+        function DisplayArrayWithMultipleElements(testCase, 
ArrayWithMultipleElements)
+            import arrow.internal.test.display.makeLinkString
+
+            array = ArrayWithMultipleElements.Array;
+            fullClassName = string(class(array)); 
+            displayName = extractAfter(fullClassName, "arrow.array.");
+            classNameLink = makeLinkString(FullClassName=fullClassName, ...
+                                           ClassName=displayName, ...
+                                           BoldFont=true);
+
+            numElementString = getNumString(3);
+            numNullString = getNumString(0);
+            header = compose("  %s with %s elements and %s null values:" + 
newline, ...
+                classNameLink, numElementString, numNullString);
+
+            body = "    " + ArrayWithMultipleElements.String + newline + 
newline;
+            expectedDisplay = char(strjoin([header body], newline));
+            actualDisplay = evalc('disp(array)');
+            testCase.verifyEqual(actualDisplay, expectedDisplay);
+        end
+
+        function DisplayArrayWithOneNull(testCase, ArrayWithOneNull)
+            import arrow.internal.test.display.makeLinkString
+
+            array = ArrayWithOneNull.Array;
+            fullClassName = string(class(array)); 
+            displayName = extractAfter(fullClassName, "arrow.array.");
+            classNameLink = makeLinkString(FullClassName=fullClassName, ...
+                                           ClassName=displayName, ...
+                                           BoldFont=true);
+
+            numElementString = getNumString(3);
+            numNullString = getNumString(1);
+            header = compose("  %s with %s elements and %s null value:" + 
newline, ...
+                classNameLink, numElementString, numNullString);
+
+            body = "    " + ArrayWithOneNull.String + newline + newline;
+            expectedDisplay = char(strjoin([header body], newline));
+            actualDisplay = evalc('disp(array)');
+            testCase.verifyEqual(actualDisplay, expectedDisplay);
+        end
+
+        function DisplayArrayWithMultipleNulls(testCase, 
ArrayWithMultipleNulls)
+            import arrow.internal.test.display.makeLinkString
+
+            array = ArrayWithMultipleNulls.Array;
+            fullClassName = string(class(array)); 
+            displayName = extractAfter(fullClassName, "arrow.array.");
+            classNameLink = makeLinkString(FullClassName=fullClassName, ...
+                                           ClassName=displayName, ...
+                                           BoldFont=true);
+
+            numElementString = getNumString(3);
+            numNullString = getNumString(2);
+            header = compose("  %s with %s elements and %s null values:" + 
newline, ...
+                classNameLink, numElementString, numNullString);
+
+
+            body = "    " + ArrayWithMultipleNulls.String + newline + newline;
+            expectedDisplay = char(strjoin([header body], newline));
+            actualDisplay = evalc('disp(array)');
+            testCase.verifyEqual(actualDisplay, expectedDisplay);
+        end
+
+        function DisplayWindowSizeThree(testCase)
+            import arrow.internal.test.display.makeLinkString
+            array = arrow.array(1:8);
+            fullClassName = string(class(array)); 
+            displayName = extractAfter(fullClassName, "arrow.array.");
+            classNameLink = makeLinkString(FullClassName=fullClassName, ...
+                                           ClassName=displayName, ...
+                                           BoldFont=true);
+
+            numElementString = getNumString(8);
+            numNullString = getNumString(0);
+            header = compose("  %s with %s elements and %s null values:" + 
newline, ...
+                classNameLink, numElementString, numNullString);
+
+            body = "    1 | 2 | 3 | ... | 6 | 7 | 8" + newline + newline;
+            expectedDisplay = char(strjoin([header body], newline));
+            actualDisplay = evalc('disp(array)');
+            testCase.verifyEqual(actualDisplay, expectedDisplay);
+
+        end
+
+        function DisplayStructArray(testCase)
+            import arrow.internal.test.display.makeLinkString
+
+            t = table((1:2)', ["A"; "B"], VariableNames=["Number", "Text"]);
+            structArray = arrow.array(t); %#ok<NASGU>
+
+            classNameLink = 
makeLinkString(FullClassName="arrow.array.StructArray", ...
+                                           ClassName="StructArray", ...
+                                           BoldFont=true);
+
+            numElementString = getNumString(2);
+            numNullString = getNumString(0);
+            header = compose("  %s with %s elements and %s null values:" + 
newline, ...
+                classNameLink, numElementString, numNullString);
+
+            body =  "    -- is_valid: all not null" + newline + ...
+                    "    -- child 0 type: double" + newline + ...
+                    "        [" + newline + ...
+                    "            1," + newline + ...
+                    "            2" + newline + ...
+                    "        ]" + newline + ...
+                    "    -- child 1 type: string" + newline + ...
+                    "        [" + newline + ...
+                    "            ""A""," + newline + ...
+                    "            ""B""" + newline + ...
+                    "        ]" + newline + newline;
+            expectedDisplay = char(strjoin([header body], newline));
+            actualDisplay = evalc('disp(structArray)');
+            testCase.verifyEqual(actualDisplay, expectedDisplay);
+        end
+
+        function DisplayListArray(testCase)
+            import arrow.internal.test.display.makeLinkString
+
+            Offsets = arrow.array(int32([0, 2, 3]));
+            Values = arrow.array([1, 2, 3]);
+
+            listArray = arrow.array.ListArray.fromArrays(Offsets, Values); 
%#ok<NASGU>
+
+            classNameLink = 
makeLinkString(FullClassName="arrow.array.ListArray", ...
+                                           ClassName="ListArray", ...
+                                           BoldFont=true);
+
+            numElementString = getNumString(2);
+            numNullString = getNumString(0);
+            header = compose("  %s with %s elements and %s null values:" + 
newline, ...
+                classNameLink, numElementString, numNullString);
+
+            body =  "    [" + newline + ... 
+                    "        [" + newline + ...
+                    "            1," + newline + ...
+                    "            2" + newline + ...
+                    "        ]," + newline + ...
+                    "        [" + newline + ...
+                    "            3" + newline + ...
+                    "        ]" + newline + ...
+                    "    ]" + newline + newline;
+            
+            expectedDisplay = char(strjoin([header body], newline));
+            actualDisplay = evalc('disp(listArray)');
+            testCase.verifyEqual(actualDisplay, expectedDisplay); 
+        end
+
+    end
+
+end
+
+function numString = getNumString(num)
+    if usejava("desktop")
+        numString = compose("<strong>%d</strong>", num);
+    else
+        numString = compose("%d", num);
+    end
+ end
\ No newline at end of file

Reply via email to