19525586 linq to objects101samples c to aplwin

Upload: ghardash

Post on 08-Aug-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    1/95

    101 LINQ to Objects Samples: From C# to APL+Win

    Ajay Askoolum

    Ajay Askoolum

    Language Integrated Query (LINQ) is an extension to C#, available from version 3.01, that is, with Visual

    Studio 2008; LINQ is a standard for querying and updating data. The syntax of LINQ integrates with that of thehost language, C# or Visual Basic.Net. Here, I am interested in LINQ to Objectsthe other implementationsare LINQ to SQL, LINQ to Entities, LINQ to DataSet, and LINQ to XMLthat deals with in-memory data or,more generally, collections.

    APL+Win, A Programming Language (APL) has been about language integrated data manipulationarrays, vectors, and nested or jagged arraysthroughout its history

    2. Here I am interested in LINQ to Objects

    as a formal deliverable from APL+Win. With its strong/unique integration of Component Object Model (COM)technology into its language features, APL+Win delivers LINQ functionality either in conjunction with C# as aCOM Server or on a standalone basis.

    In this article, I present LINQ to Objects implemented in C# and APL+Win side by side. Above all, LINQprovides a platform for extolling the capabilities of APL+Win using the same vocabulary as a C# developer!The smallprice of this opportunity is the acquisition of a grasp of the LINQ to Objects concepts.

    I urge you to read the Partitioning Operators section even if LINQ to Objects is not within your sphere ofinterest right now. For APL+Win users, this group of operators will be very familiar. That C# is nowincorporating these features into the language does indeed suggest that APL+Win is a language that is aheadof time.

    Table of Contents

    Table of Contents...........................................................................................................................11.1 The Agenda .........................................................................................................................5

    1.1.1 The terms of reference ...............................................................................................................61.1.2 The payoff for general APL+Win programming..........................................................................6

    1.1.2.1 Replicating the experience ................................................................................................................. 71.1.3 APL+Win and Dot Net Accessibility............................................................................................91.1.4 Why LINQ to Objects?................................................................................................................9

    1.2 Getting Started ....................................................................................................................91.2.1 Understanding the code ...........................................................................................................10

    1.2.1.1 Language symbols............................................................................................................................ 111.2.1.2 What is the question? ....................................................................................................................... 11

    1.3 Restriction Operators ........................................................................................................121.3.1 Where - Simple 1......................................................................................................................12

    1.3.1.1 C# code ............................................................................................................................................ 121.3.1.2 APL+Win code................................................................................................................................. 131.3.1.3 Understanding the standard result .................................................................................................... 131.3.1.4 Method Signature ............................................................................................................................. 141.3.1.5 Further tests...................................................................................................................................... 14

    1.3.2 Where - Simple 2......................................................................................................................15 1.3.3 Where - Simple 3......................................................................................................................16

    1 Dot Net Framework 3.5.2 Unfortunately, LINQ and APL+Win use different jargon to describe identical concepts; I expect that the LINQ vocabulary will prevail.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    2/95

    Page 2 of 71

    1.3.4 Where - Drilldown .....................................................................................................................17 1.3.5 Where - Indexed .......................................................................................................................19

    1.4 Projection Operators .........................................................................................................191.4.1 Select - Simple 1 ......................................................................................................................19

    1.4.1.1 Linq6 in focus .................................................................................................................................. 201.4.2 Select - Simple 2 ......................................................................................................................20 1.4.3 Select - Transformation ............................................................................................................21

    1.4.4 Select - Anonymous Types 1....................................................................................................22 1.4.5 Select - Anonymous Types 2....................................................................................................22 1.4.6 Select - Anonymous Types 3....................................................................................................23 1.4.7 Select - Indexed........................................................................................................................23 1.4.8 Select - Filtered ........................................................................................................................24 1.4.9 SelectMany - Compound from 1...............................................................................................24 1.4.10 SelectMany - Compound from 2.............................................................................................25 1.4.11 SelectMany - Compound from 3.............................................................................................25 1.4.12 SelectMany - from Assignment ..............................................................................................26 1.4.13 SelectMany - Multiple from.....................................................................................................27 1.4.14 SelectMany - Indexed.............................................................................................................28

    1.5 Partitioning Operators .......................................................................................................281.5.1 Take - Simple ...........................................................................................................................29 1.5.2 Take - Nested ...........................................................................................................................29

    1.5.2.1 First two customers in Washington and all their orders .......... ............. ............. ............ ............. ...... 291.5.2.2 First 3 customers in Washington and their first 5 orders.... ............ ............. ........... ............. ............. 301.5.3 Skip - Simple.............................................................................................................................30 1.5.4 Skip - Nested ............................................................................................................................30 1.5.5 TakeWhile - Simple ..................................................................................................................31 1.5.6 TakeWhile - Indexed.................................................................................................................31 1.5.7 SkipWhile - Simple ...................................................................................................................31 1.5.8 SkipWhile - Indexed..................................................................................................................32

    1.6 Ordering Operators ...........................................................................................................321.6.1 OrderBy - Simple 1 ...................................................................................................................32 1.6.2 OrderBy - Simple 2 ...................................................................................................................32 1.6.3 OrderBy - Simple 3 ...................................................................................................................32

    1.6.3.1 Where is the difference?........ ............ ............. ........... ............. ............. ............ ........... ............. ......... 331.6.4 OrderBy - Comparer .................................................................................................................33

    1.6.5 OrderByDescending - Simple 1 ................................................................................................34 1.6.6 OrderByDescending - Simple 2 ................................................................................................34 1.6.7 OrderByDescending - Comparer ..............................................................................................34 1.6.8 ThenBy - Simple .......................................................................................................................35 1.6.9 ThenBy - Comparer ..................................................................................................................35 1.6.10 ThenByDescending - Simple ..................................................................................................35 1.6.11 ThenByDescending - Comparer .............................................................................................36 1.6.12 Reverse ..................................................................................................................................36

    1.7 Grouping Operators...........................................................................................................371.7.1 GroupBy - Simple 1 ..................................................................................................................37 1.7.2 GroupBy - Simple 2 ..................................................................................................................37 1.7.3 GroupBy - Simple 3 ..................................................................................................................38 1.7.4 GroupBy - Nested.....................................................................................................................38 1.7.5 GroupBy Comparer ...............................................................................................................40

    1.7.6 GroupBy Comparer, Mapped ................................................................................................40 1.8 Set Operators ....................................................................................................................411.8.1 Distinct - 1.................................................................................................................................41 1.8.2 Distinct - 2.................................................................................................................................41 1.8.3 Union - 1 ...................................................................................................................................42 1.8.4 Union - 2 ...................................................................................................................................42 1.8.5 Intersect - 1...............................................................................................................................43 1.8.6 Intersect - 2...............................................................................................................................43 1.8.7 Except - 1..................................................................................................................................44 1.8.8 Except - 2..................................................................................................................................44

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    3/95

    Page 3 of 71

    1.9 Conversion Operators .......................................................................................................441.9.1 To Array ....................................................................................................................................44 1.9.2 To List .......................................................................................................................................45 1.9.3 To Dictionary.............................................................................................................................45 1.9.4 OfType......................................................................................................................................46

    1.10 Element Operators ..........................................................................................................461.10.1 First - Simple ..........................................................................................................................46

    1.10.2 First Condition (missing at URL) .........................................................................................471.10.3 First - Indexed.........................................................................................................................47 1.10.4 FirstOrDefault - Simple ...........................................................................................................47 1.10.5 FirstOrDefault - Condition.......................................................................................................48 1.10.6 FirstOrDefault - Indexed .........................................................................................................48 1.10.7 ElementAt ...............................................................................................................................49

    1.11 Generation Operators......................................................................................................501.11.1 Range .....................................................................................................................................50 1.11.2 Repeat ....................................................................................................................................50

    1.12 Quantifiers .......................................................................................................................501.12.1 Any - Simple ...........................................................................................................................50 1.12.2 Any - Indexed .........................................................................................................................51 1.12.3 Any - Grouped ........................................................................................................................51 1.12.4 All - Simple..............................................................................................................................52

    1.12.5 All - Indexed............................................................................................................................52 1.12.6 All - Grouped ..........................................................................................................................52

    1.13 Aggregate Operators.......................................................................................................531.13.1 Count - Simple........................................................................................................................53 1.13.2 Count - Conditional.................................................................................................................53 1.13.3 Count - Indexed ......................................................................................................................54 1.13.4 Count - Nested .......................................................................................................................54 1.13.5 Count - Grouped.....................................................................................................................55 1.13.6 Sum - Simple ..........................................................................................................................55 1.13.7 Sum - Projection .....................................................................................................................55 1.13.8 Sum - Grouped .......................................................................................................................56 1.13.9 Min - Simple............................................................................................................................56 1.13.10 Min - Projection.....................................................................................................................56 1.13.11 Min - Grouped.......................................................................................................................57

    1.13.12 Min - Elements......................................................................................................................57 1.13.13 Max - Simple.........................................................................................................................58 1.13.14 Max - Projection....................................................................................................................58 1.13.15 Max - Grouped......................................................................................................................58 1.13.16 Max - Elements.....................................................................................................................59 1.13.17 Average - Simple ..................................................................................................................59 1.13.18 Average - Projection .............................................................................................................59 1.13.19 Average - Grouped ...............................................................................................................60 1.13.20 Fold - Simple ........................................................................................................................60 1.13.21 Fold - Seed ...........................................................................................................................60

    1.14 Miscellaneous Operators ................................................................................................611.14.1 Concat - 1 ...............................................................................................................................61 1.14.2 Concat - 2 ...............................................................................................................................61 1.14.3 EqualAll - 1 .............................................................................................................................62

    1.14.4 EqualAll - 2 .............................................................................................................................62 1.14.4.1 EqualAll - 2 : Extension................................................................................................................. 63

    1.15 Custom Sequence Operators..........................................................................................631.15.1 Combine .................................................................................................................................63

    1.15.1.1 C#:APL+Win comparison.............................................................................................................. 641.16 Query Execution..............................................................................................................64

    1.16.1 Deferred..................................................................................................................................64 1.16.2 Immediate ...............................................................................................................................65 1.16.3 Query Reuse ..........................................................................................................................65

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    4/95

    Page 4 of 71

    1.17 Time for 101 APL+Win samples? ...................................................................................65

    References....................................................................................................................................66

    Appendix A Product & Customer Lists ..................................................................................67

    Index ..............................................................................................................................................69

    Code Listings................................................................................................................................71

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    5/95

    101 LINQ to Objects Samples: From C# to APL+Win

    Ajay Askoolum

    Ajay Askoolum

    1.1The Agenda

    The agenda is set at the following Universal Resource Locator (URL):

    http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx

    Alas, the material at his URL does not refer to APL+Win at all, as to be expected!

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    6/95

    Page 6 of 71

    A much more serious criticism is that the URL does not provide completecode samples. A number ofthe code snippets do not lend themselves to simple copy & paste into another project; some of thesample codes are also incorrect

    3. Although the basic code listings are useful, the supporting code

    dependencies are missing4.

    The code samples simply demonstrate concepts5: the results of sample queries (written to the

    console) shown at the URL provide valuable insight into the functionality, especially from the point ofview of replicating them in APL+Win.

    If you count the number of samples, there are fewer than the 101 suggested by the title; and anumber of themsuch as Linq60do not work. This is not only misleading but also highlyunsatisfactory, not least because of the pedigree of its originMicrosoftand the fact that this passesfor reference material.

    In spite of all the shortcomings, this provides an excellent opportunity for exploring a brand new feature ofthe contemporary flagship language; ore to the point, this provides the terms of reference for illustratingAPL+Win techniques that have been part of the language from the outset. I have included the missingsamples in this article.

    1.1.1The terms of reference

    The code samples at the URL have the data that they manipulate either hard-coded or drawn from supportingfunctions. The functions are not parameterised.

    My objective is to write a COM server in C# and use it with APL+Win, and to compare the results from C#with those from APL+Win, in the APL+Win immediate mode. In order to extend the scope of this exercise,some of the methods in C# and APL also accept arguments in client/server mode.

    This serves several purposes.

    C# uses complex data types such as the product and customer lists; although these are akin toAPL+Wins nested arrays, there is an important difference. C# refers to the data items by name,something that is notpossible in APL+Win. In the APL+Win environment, I refer to the data items bytheir position or cardinal order in the nested array. Therefore, I also need to coax C# to supply thedata in a simpler nested/jagged array format for use by APL+Win.

    A number of refinements in the C# examples are not obvious from the examples given. For example,UNION disregards duplicated elements in its result; appropriate arguments to such functions canhighlight such features.

    Overall, this demonstrates C# and APL+Win in a fully functional client/server configurationan optionfor any application.

    1.1.2The payoff for general APL+Win programming

    LINQ techniques are interesting from point of view of APL+Win for several reasons.

    All data in APL+Win are objects or, for a simplistic view, arrays; LINQ deals with such objects.

    3For example, the code for the class CustomSequenceOperators is incorrect; Linq96 shows wordsA.EqualAll(wordsB) which should be

    wordsA.SequenceEqual(wordsB).4

    For example, functions such as GetProductList and GetCustomerList, are missing.5 The code outputs results to the console: as such, modifications are required to incorporate them in class libraries so that they can take arguments and

    return results.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    7/95

    Page 7 of 71

    Although C# and APL+Win operate in disparate environments, this paper demonstrates how well thetwo can work together (the prospects for Visual APL which works from the same environment as C#are even better!).

    I have not developed optimised code for my purpose or designed code for re-use. However, there aresubtle opportunities to harvest APL+Win idioms. The APL+Win code samples generally use one-dimensional arrays (vectors or nested vectors): they can be generalised for multi-dimensional arrays.

    There is an opportunity to familiarise yourself with another jargon, that of LINQ (and C#): this will beuseful for the future in many ways, even if this is not apparent right now.

    1.1.2.1Replicating the experience

    I am using APL+Win version 9, with Visual Studio 2008 with Service Pack 1, under Windows XP Professionalwith Service Pack3.

    The APL+Win workspace, LINQ to OBJECTS.W3, is accessible with version 9 of the interpreter.

    If you have Visual Studio 2008 (any hybrid), one of your options is to attempt to load the project andrecompile it: I have not tested this project with every version of Visual Studio 2008. This will register the COMDynamic Library (DLL) as required, without further intervention from you.

    If you do not have Visual Studio 2008

    6

    , you will need to do the following:

    Download and install Dot Net Framework 3.5

    Register the COM DLL, LINQ.DLL, as follows:

    The critical steps:

    1. Copy the file LINQ.DLL to a desired location on the target computer, say, C:\APLWIN\C#COM\LINQ\

    2. Locate the file RegAsm.exe. Although we have been using Framework 3.5, the most recent version of theregistration tool came with Framework 2.0.

    C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe

    3. Run the following line from the command prompt:

    If you use other automated installation software such as InstallShield to deploy your application, it needsto execute the above line.

    4. If you need to remove the DLL from the computer, run the following line from the command prompt:

    The paths may be different on your computer; change the commands as appropriate. Refer tohttp://msdn.microsoft.com/enus/library/tzat5yw6(VS.71).aspxfor more details on REGASM.EXE.

    On successful registration, you should be able to recreate the following:

    6 This presents the same scenario as that when deploying your own Dot Net DLL.

    C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe /U "C:\APLWIN\C#COM\LINQ\LINQ.DLL"

    C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe /codebase "C:\APLWIN\C#COM\LINQ\LINQ.DLL"

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    8/95

    Page 8 of 71

    Depending on how you use the supplied code, you may receive one of the following (or similar) errors:

    WI ERROR: mscorlib exception 80070015 The device is not ready.

    WI ERROR: mscorlib exception 80070003 Could not find a part of the path'C:\AJAY\C#\VS2008\VS2008\LINQ to Objects\LINQ\customers.xml'.

    This arises as a result of a hard-coded path reference is DATA.CS. The resolution is to ensure that the

    path specified reflects the location of CUSTOMERS.XML in your preferred directory structure7.

    The freelydownloadable XML NOTEPAD 2007, see below, is a useful tool for creating and examiningXML files interactively. You may want to use this tool to examine/audit the results of LINQ queries that useCUSTOMERS.XML.

    7 The project needs re-compilation after any changes to the code.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    9/95

    Page 9 of 71

    1.1.3APL+Win and Dot Net Accessibility

    An often raised complaint, perhaps more often than necessary given the respective infrastructure and lineageof APL+Win and C#, is that APL+Win does not, but should, implement a system function, NET, to enableaccess to the Dot Net Libraries. I do not subscribe to this view for the following reasons:

    Such an accessibility function will not enhance or optimise the existing legacy of APL+Winapplications such that they can benefit from enhancements in the technology that Dot Net heralds. It

    might be useful for future development: in this context, Visual APL offers better prospects for return oninvestment since it is closely aligned to APL+Win and is a true Dot Language, not just a Dot NETaware one.

    Such a function allows access to the Dot NET foundation class libraries only and not to Dot NETlanguages such as C#

    8. Quite often, it is necessary to write APL Code to glue calls to the foundation

    class libraries. This implies that a managed and strongly typed environment (Dot Net) is coerced intoan un-managed and loosely typed environment (APL). This has strong implications for applicationdebugging and maintenance. Besides, in such as scenario APL is always playing catch up toimprovements in the Dot Net framework.

    APL+Win offers a robust COM interface that enables any user-built DLL to be deployed from withinAPL+Win. Therefore, the Dot NET environment can be kept separate from the APL+Win environmentwith several advantages: first, it is not the APL developer who has to code the Dot Net functionalitya

    Dot Net expert can do it independently of APLand second, each environment can be debuggedseparately or together. Play the media file APLWINDEBUGSC#.WMV for an illustration.

    1.1.4Why LINQ to Objects?

    LINQ to Objects is especially interesting from an APL point of view.

    It is a set of standard operators that eliminates the need for the developer to write loops5.

    It standardises the means of doing routine tasks relating to data in memory and has a syntax that isvery much like that of the host language.

    Is that not what APL+Win is (has always been) about?

    1.2Getting Started

    The general format of the illustrations below is to state the purpose of the code sample, list the C# codesample, list the APL+Win function and then to illustrate and discuss the results.

    The 101 code samples are named Linq1 to Linq101, as seen at the URL; I have retained this convention incoding the APL+Win counterpart functions in order to maintain a 1:1 correspondence.

    For some functions, there is an extension function, named LinqnEx (ndesignates the numeric sequenceof the code sample): I have used this to elaborate on extensions to the functionality in question.

    The source data for the code samples, where required, is internallysupplied as complex data types to theC# functions: GetProductList and GetCustomerList are two such examples. I have coded GetProductListExand GetCustomerListEx which supply the same data as a simple type to APL+Win. Please refer to the end ofthis document for a complete listing

    9of the C# codeEXPLORE.CS and DATA.CSthat underlies the COM

    DLL.

    8 Remember that LINQ fits within a Dot NET language, such as C# or Visual Basic.NET.9 I printed the code from Visual Studio 2008 and appended to this PDF.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    10/95

    Page 10 of 71

    For the sake of clarity as well as completeness, I recommend that you refer to the code sample at the URLand this document concurrently and make appropriate allowance for the errors and omission I havehighlighted.

    Given that the C# COM DLL, LINQ.DLL, is registered, the following function establishes an instancethereof; it runs as the latent expression on loading the workspace LINQ to OBJECTS.W3 and should persistfor the duration of the session:

    LINQ[1] Ajay Askoolum[2] wself'lq' wi 'Create' 'LINQ.Explore'

    The first example, discussed next, is deliberately verbose: this is to familiarise you with the pattern for allthe other samples. Therefore, you should study this example first and then may navigate to any other sample,if necessary.

    1.2.1Understanding the code

    These pages do not contain a tutorial on either C# or APL+Win: such a task is beyond the scope of thisexercise. However, the VS2008 project and the APL+Win workspace contain all the code used herein.

    When working through these pages, it may be useful to bear in mind the following:

    Unlike APL+Win which has index origin default to zero, C# always works with index origin set to zerothere is no other option. The APL+Win code I have used here is index-origin independent.

    Both APL+Win and C# are case sensitive.

    Both APL+Win and C# use square brackets for indexing; for indexing multi-dimensional arrays, APL+Winuses semi-colon and C# uses comma to separate the co-ordinates.

    The syntax for localisation or scope determination is different in the two languages. With APL+Win, anyname included in the header of a function and separated by a semi-colon has the effect of restricting thescope of that name to that function only

    10. In C#, any name included within a pair of opening and closing

    braces is local.

    In C#, a comma separates elements of an array/vector; the same is true (but optional) for APL+Winnumeric elements (although it is more conventional to use spaces) of an array/vector.

    Unlike APL+Win which uses single and double quotesin pairsinterchangeably, C# uses double quotesfor literals or strings and single quotes for data type char.

    C# uses \ as an escape character, embedded in literals; for example, Prime\r\nExample indicates thatcarriage return and line feed separate the two words. C# has verbatimstrings; these are prefixed by @ andsimply instruct C# to take a literal at face value. For example, with @Prime\r\nExample, C# will not interpret\r\n as carriage return and line feed. If you specify a string, say a path as c:\ajay, the options are to write eitherc:\\ajay or @c:\ajay. APL+Win does not have embedded escape sequence characters but can pass literalsto C# using the C# conventions.

    How many statement delimiters does APL+Win have? It might surprise you to learn that there are two:

    diamond () and linefeed. C# has a single statement delimiter, semi-colon; statements may span severallines. Unlike APL+Win where these delimiters are optional, the C# delimiter is mandatory.

    10 In order to keep this simple, I will not elaborate on dynamic localisation here; this does not exist in C#.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    11/95

    Page 11 of 71

    If you are lured into the belief that C# is difficult, it might be an opportune moment to remind yourself howdifficult APL has been between the time when you started to learn it and the present, when you havemastered the language.

    C# is a pleasant experience. From my point of view, C# is no more difficult than APL+Win and the twolanguages share a common attribute, namely, it is possible to write code without understanding all thesubtleties of the language. Unlike APL+Win, C# has a wealth of sources for worked examples and general

    reference; therefore, in theory, C# should be easier to learn.1.2.1.1Language symbols

    This article involves two languages, C# and APL+Win. The context involves the examination of the code side-by-side. As an aid to understanding the code, the following table is useful.

    APL+Win C# Description = Comes from or becomes

    = == Equality comparison

    != Not equal to

    < < Less than

    > Greater than

    >= Greater than or equal to (not less than)

    | % Modulus

    1.2.1.2What is the question?

    The question mark is part of the C# language; it is like an APL+Win primitive.

    double?[] doubles = { 1.7, 2.3, 4.1, 1.9, null, 2.9 };

    In the above line, the question mark indicates that any element of the vector can have a nullvalue.

    Sign = (MyVal == 0) ? 0 : (MyVal < 0) ? -1 : 1;

    In the latter example, the question mark indicates if: read the line as the sign of a scalar MyVal is 0 if it iszero, else if it is less than one, the sign is -1 else it has a default value of 1

    C# has a data type that is also of interest as it occurs in the code samples: null. C# is a strongly typedlanguage; APL+Win is a type-inferred language. The nulldata type is a difficult concept; technically, it meansa missing value or that a variable has been declared but not assigned a value.

    APL cannot have a variable that is unassigned since it is not a declarative language. However, in somecontexts, 0/0 or 0/ are appropriate to emulate a null value in APL+Winit also has a null value.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    12/95

    Page 12 of 71

    1.3Restriction Operators

    This group of operators apply relational criteria to data and return the elements that satisfy the criteria; the keyconcept is to elicit results using relational operators on lists, or vectors, or arrays, numeric and character.Another way to understand this group of operators is to think of them as filtering an existing object, theargument, and creating a new object, the result.

    APL+Win supports the full set of relational operators found in C#; the difference is that LINQ also hasnames for some of the operators whereas APL+Win has primitives.

    1.3.1Where - Simple 1This example shows the selection, from a given vector, of all elements whose value is greater than five.

    1.3.1.1C# code

    At the URL, this sample is listed as follows:

    publicvoid Linq1(){int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };var lowNums = from n in numbers

    where n < 5select n;

    Console.WriteLine("Numbers < 5:");foreach (var x in lowNums)

    { Console.WriteLine(x);}

    }

    The following is apparent:

    The data that passes for the argument to the function is hard-coded, making it inconvenient, if notimpossible, to test the function with alternative data.

    The function does not return a result; it writes to the console. Therefore, it would be impossible to returnresults to or pass data from APL+Win.

    Therefore, in order to overcome these limitations, I have modified the code to read as follows:

    publicint[] Linq1(int[] numbers, int threshold){

    var lowNums = from n in numberswhere n < thresholdselect n;

    return lowNums.ToArray();}

    Now the function will

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    13/95

    Page 13 of 71

    Accept two arguments, the data and the threshold that is used to filter the data.

    Return a result instead of printing it to the console.

    1.3.1.2 APL+Win code11

    All the APL+Win functions assume that the instance of the C# COM DLL exists already and that it is thedefault left-hand argument of wi the function.

    ZLinq1;L;R;Linq;APL[1] RESTRICTION OPERATOR: Where - Simple1[2] L(2?10)?15 With possible replication[3] R?10[4] Linqwi 'Linq1' L R[5] APL(L

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    14/95

    Page 14 of 71

    On the face of it, the sample shows the result as an nby 1 array whereas the APL equivalent shows it asa vector of nelements. In fact, the sample is appending a carriage return

    12after each element: the results are

    identical.

    1.3.1.4Method Signature

    The previous example illustrates how a method inside the COM is callable from APL+Win with arbitraryarguments. However, you should verify how the signature of a methodhow it is codedbefore attempting acall.

    The syntax of a method may be established by a visual examination of the coderefer to Appendix Aeither for code listingsor as follows:

    wi '?Linq1'XLinq1 method:Result@Array_Long WI 'XLinq1' numbers@Array_Long threshold@Long

    Note that this query returns both the name and type of each argument, and indicates the type of the resultreturned, if any.

    1.3.1.5Further tests

    The APL+Win function, Linq1, creates random argumentssee lines [2]-[3]and permits tests to be runquickly. The following illustrates the results of three further tests.

    12 WriteLine appends \r\n (carriage return and line feed) to its argument.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    15/95

    Page 15 of 71

    The argument numbers is listed first (as L), followed by the argument threshold(as R). Then the resultreturned by the COM DLL is listed (as Linq), followed by the corresponding result from APL+Win (as APL).The label Matched?shows 1 when the results from C# and APL+Win match else it shows 0.

    This concludes the basic guide to reading each of the remaining examples/samples13

    .

    1.3.2Where - Simple 2

    This query lists all the products that are out of stock. The list or product, unlike the list of customers held in anexternal XML file, is built using code in DATA.CS. The first two products are built with these lines of code:

    C# accesses the individual elements of data by name, shown here in the VS2008 Immediate Window.

    This is a complex C# data type; it comprises of several simple C# types. The data structure Product isbuild as follows:

    public class Product{

    publicint ProductID;publicstring ProductName;publicstring Category;publicdecimal UnitPrice;publicint UnitsInStock;

    }

    In APL+Win, the simplest approach is to code the C# COM DLL to supply the data14

    . Everything isavailable except that the names of the individual elements.

    13 This is LINQ! an advancement to C#. .APL+Win has done this from inception, has it not?14 This avoids transcription errors and facilitates comparisons.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    16/95

    Page 16 of 71

    Finally, let us see the results of the LINQ Query in APL+Win:

    ZLinq2;L;R;Linq;APL;products[1] RESTRICTION OPERATOR: Where - Simple 2[2] Linqwi 'Linq2'[3] productswi 'GetProductListEx' ProductID ProductName Category

    UnitPrice UnitsInStock[4] L1products Last element is UnitsInStock[5] APL(io+1)(L=0)/products[6] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

    The results match!

    1.3.3Where - Simple 3

    This query selects items from the product list where the number of items in stock is non-zero and the item's

    unit price is greater than 3.00.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    17/95

    Page 17 of 71

    The results match; they are produced by the following function:

    ZLinq3;L;R;Linq;APL;products[1] RESTRICTION OPERATOR: Where - Simple 3[2] Linqwi 'Linq3'[3] productswi 'GetProductListEx' ProductID ProductName Category

    UnitPrice UnitsInStock[4] L(io+3)products Fourth element is UnitPrice[5] R1products Last (fifth) element is UnitsInStock[6] APL(io+1)((R>0)^L>3)/products[7] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

    I am using a screenshot to capture the results of functions, especially where the results are verbose, as inthis instance. This is purely a convenience for formatting the content of this document. For your exploration,you may choose to stop the functions after the penultimate line and then examine or debug the individualcomponents of the results at your leisure; the last line shows the complete results.

    How does it work? With C# a two-dimensional string array, potentially, each row has a different length: thelength of the number of characters in it. With APL+Win, all rows have the same lengththey are padded withtrailing space making up a length equal to the longest string in the array. However, with a nested string vector,each element occupies only enough space to accommodate its own length irrespective of the length of co-existing elements; this feature simplifies string relational comparisons.

    1.3.4Where - Drilldown

    This query prints a list of customers from the state of Washington along with their orders. The list of customersholds customers details and their orders.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    18/95

    Page 18 of 71

    Linq4LINQ LAZYK Lazy K Kountry Store 10482 21/03/1997

    10545 22/05/1997TRAIH Trail's Head Gourmet Provisioners 10574 19/06/1997

    10577 23/06/199710822 08/01/1998

    WHITC White Clover Markets 10269 31/07/199610344 01/11/1996

    10469 10/03/199710483 24/03/199710504 11/04/199710596 11/07/199710693 06/10/199710696 08/10/199710723 30/10/199710740 13/11/199710861 30/01/199810904 24/02/199811032 17/04/199811066 01/05/1998

    APL LAZYK Lazy K Kountry Store 10482 21/03/199710545 22/05/1997

    TRAIH Trail's Head Gourmet Provisioners 10574 19/06/199710577 23/06/199710822 08/01/1998

    WHITC White Clover Markets 10269 31/07/199610344 01/11/199610469 10/03/199710483 24/03/199710504 11/04/199710596 11/07/199710693 06/10/199710696 08/10/199710723 30/10/199710740 13/11/199710861 30/01/199810904 24/02/199811032 17/04/199811066 01/05/1998

    Match? 1

    The function is defined as follows:

    ZLinq4;Linq;APL[1] RESTRICTION OPERATOR: Where - DrillDown[2] Linqwi 'Linq4'[3] APLwi 'GetCustomerListEx' CustomerID 1,CompanyName

    2,Address 3,City 4,Region 5,PostalCode 6,Country 7,Phone 8,Fax 9,Orders10

    [4] APL(((io+4)APL)'WA')/APL Just those in the WA Region - is the fifth element

    [5] APL(io+0 1 9)APL , & i.e. First, Second & Tenth element

    [6] ((io+2)APL)1 1 0/(io+2)APL & i.e First

    & Second element of , now the third element[7] APLAPL[8] Z('LINQ' 'APL' 'Match?'),[io+0.5] Linq APL (LinqAPL)

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    19/95

    Page 19 of 71

    The comments in this function provide valuable clues on the computation of the result. If the logic is notself-evident, you need to examine the function line by line.

    The COM method GetCustomerListEx hides a subtlety: because APL+Win does not support the datetimedata type, the method returns the date information as a string, formatted in short date regional format. I amusing the UK regional format, that is, dd/mm/yyyy

    15. For reporting purposes, this technique is adequate, as it

    does not involve any date arithmetic.

    1.3.5Where - Indexed

    This query uses an indexed Where clause to print the name of each number, from 0-9, where the length of thenumber's name is shorter than its value. In this case, the code is passing a lamda expression which isconverted to the appropriate delegate type. The body of the lambda expression tests whether the length of thestring is less than its index in the array.

    At this point, the reality of the C# jargon hits home; as mentioned, it is beyond the scope of the presentobjective. Briefly, a lambda expression is an anonymous (one without a name) function and containsstatements like any function. For the lambda operator => read goes to. A good reference on C# 3.0 is aprime requisite for understanding the Linq to Objects samples: at the very least you need to read the words

    accompanying each example at the URL http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx.

    Linq5

    LINQ five six seven eight nineAPL five six seven eight nineMatch? 1

    The function is defined as follows:

    ZLinq5;Linq;APL[1] RESTRICTION OPERATOR: Where - Indexed[2] Linqwi 'Linq5'[3] APL"zero" "one" "two" "three" "four" "five" "six" "seven" "eight"

    "nine"[4] APL((APL)

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    20/95

    Page 20 of 71

    APL+Win does not support the facility to select a number and perform an arithmetic operation on thatnumber in one expression. However, APL+Win can produce the same result.

    Linq6LINQ 6 5 2 4 10 9 7 8 3 1APL 6 5 2 4 10 9 7 8 3 1

    Match? 1

    The APL function is defined as follows:

    ZLinq6;Linq;APL[1] Projection Operators - Select Simple 1[2] Linqwi 'Linq6'[3] APL1+ 5 4 1 3 9 8 6 7 2 0[4] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

    1.4.1.1Linq6 in focus

    The alternative or conventional C# way of achieving the same result is:

    publicint[] Linq6alt()

    {int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };int[] res = newint[numbers.Length];for (int i = 0;i< numbers.Length;i++){

    res[i]=numbers[i]+0;}return res;

    }

    It is now apparent that this LINQ query simply saves the developer two things: first, an explicit loop andsecond the facility to return a subset of the argument vector by the use of a where clause, if necessary.

    In fact, Linq6 hides a much more important subtlety: if, say, only even numbers are retained from the

    argument, the alternative solution will not work since it is impossible to determine how many elements areeven without executing another loop to determine it first. Then, the solution to a simple problem is at risk ofbecoming a clutter of code.

    Of course, the APL solution takes such a restriction in its stride16

    :

    1+(0=2|APL)/APL5 4 1 3 9 8 6 7 2 05 9 7 3 1

    1.4.2Select - Simple 2

    16 Unlike C#, APL+Win can resize/reorder arrays dynamically.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    21/95

    Page 21 of 71

    This query returns the name of every product in the product list. The matching APL+Win result comes fromthe following function:

    ZLinq7;Linq;APL[1] RESTRICTION OPERATOR: Where - Indexed[2] Linqwi 'Linq7'[3] APL(io+1)wi 'GetProductListEx' ProductID ProductName Category

    UnitPrice UnitsInStock. ProductName is second element[4] Z('LINQ' 'APL' 'Match?'),[io-0.5]Linq APL (LinqAPL)

    1.4.3Select - Transformation

    This query returns the name of each number in an integer array by indexing into a second array that containsthe names. The C# solution works because it works in index origin zero.

    APL+Win can return the same result in index origin one or zero; the result drawn from the C# DLL work inthe only index origin possible, zero, irrespective of the setting in APL+Win.

    io1 Linq8LINQ five four one three nine eight six seven two zeroAPL five four one three nine eight six seven two zero

    Match? 1

    io0 Linq8LINQ five four one three nine eight six seven two zeroAPL five four one three nine eight six seven two zero

    Match? 1

    The APL+Win function is defined as follows:

    ZLinq8;Linq;APL[1] Projection Operators: Select - Transformation[2] Linqwi 'Linq8'[3] APL5 4 1 3 9 8 6 7 2 0[4] APL("zero" "one" "two" "three" "four" "five" "six" "seven" "eight"

    "nine" )[APL+io][5] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    22/95

    Page 22 of 71

    1.4.4Select - Anonymous Types 1

    This query returns each element of its argument in uppercase and lowercase. With APL+Win, I will not use theCharUpper or CharLower Application Programming Interface (API) calls in order to keep the comparisonstrictly at the language level.

    The solution is quite simple: substitute each of the 26 characters with one in the corresponding case.

    RL LCase R[1] Return R in uppercase[2] Lio[3] :for i :in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[4] ((i=,R)/,R)'abcdefghijklmnopqrstuvwxyz'[L][5] LL+1[6] :endfor

    RL UCase R[1] Return R in uppercase[2] Lio[3] :for i :in 'abcdefghijklmnopqrstuvwxyz'[4] ((i=,R)/,R)'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[L][5] LL+1

    [6] :endfor

    The following APL+Win function produces a comparison of the solution:

    ZLinq9;Linq;APL[1] Projection Operators - Select - Anonymous Type 1[2] Linqwi 'Linq9'[3] APL,/(UCase "aPPLE" "BlUeBeRrY" "cHeRry") (LCase "aPPLE"

    "BlUeBeRrY" "cHeRry")[4] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

    The results match:

    Linq9LINQ APPLE apple BLUEBERRY blueberry CHERRY cherryAPL APPLE apple BLUEBERRY blueberry CHERRY cherry

    Match? 1

    1.4.5Select - Anonymous Types 2

    This query iterates over the elements of an input integer vector and returns the elements name and parity,that is, whether it is odd or even. It works because string vector holds the digit names in numerical sequence,starting with zerothe index origin in C#.

    The APL+Win functionindex origin independentis:

    ZLinq10;Linq;APL[1] Projection Operators: Select - Anonymous Types 2[2] Linqwi 'Linq10'[3] APL5 4 1 3 9 8 6 7 2 0[4] APL(("zero" "one" "two" "three" "four" "five" "six" "seven" "eight"

    "nine")[io+APL]), ('even' 'odd')[io+2|APL]

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    23/95

    Page 23 of 71

    [5] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

    1.4.6Select - Anonymous Types 3

    This query returns the name of every product in the product list along with the category of the product and itsunit price. The C# version renames UnitPrice to Price. As mentioned, APL+Win identifies elements of anested array by its cardinal order and not by name.

    The APL+Win function that produces a matching result:

    ZLinq11;Linq;APL

    [1] Projections Operators: Select - Anonymous Types 3[2] Linqwi 'Linq11'[3] APL0 1 1 1 0/wi 'GetProductListEx' ProductID ProductName Category

    UnitPrice UnitsInStock[4] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)[5] 0[6] (ProductName Category Price),[io+1]APL

    Note line [6]: APL+Win can easily reclaim the names of the columns in the result: C# retains the namesintrinsically and APL+Win assigns them arbitrarily.

    1.4.7Select - Indexed

    This query returns the value of each element in a vector of integers whether the element matches its indexin index origin zeroin the vector. The index of each element is inferred rather than index in another vectorholding the actual indices.

    Linq12LINQ APL Match?

    5 0 5 0 14 0 4 01 0 1 03 1 3 19 0 9 08 0 8 06 1 6 17 1 7 12 0 2 00 0 0 0

    Although the results match, there is a deviation in the result: 1 and 0 are shown instead of true andfalse, respectively. The APL+Win function:

    ZLinq12;Linq;APL[1] Projections Operators: Select Indexed[2] Linqwi 'Linq12'[3] APLAPL (APL=(-io)+APL5 4 1 3 9 8 6 7 2 0)[4] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    24/95

    Page 24 of 71

    1.4.8Select - Filtered

    This query prints the name of each element of an integer vector that is less than five; it combines select andwhere to build a simple query that indexes into another string vector that contains the names of the elements.All elements are less than nine.

    Linq13LINQ APL Match?

    four four 1one onethree threetwo twozero zero

    The function is:

    ZLinq13;Linq;APL[1] Projection Operators: Select - Filtered[2] Linqwi 'Linq13'[3] APL"zero" "one" "two" "three" "four" "five" "six" "seven"

    "eight" "nine"[4] APLAPL[io+(5 4 1 3 9 8 6 7 2 0

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    25/95

    Page 25 of 71

    1.4.10SelectMany - Compound from 2

    This query returns all orders whose total is less that 500; each such order is identified by the CustomerID andOrderID. The list of customers holds each CustomerID uniquely but the orders details are recurring.

    APL+Win solution is:

    ZLinq15;Linq;APL;Select;CustomerID;Orders

    [1] Projection Operators: SelectMany - Compound from 2[2] Linqwi 'Linq15'[3] 0 0def ' ZL Select R',tcnl,'[1] ZL/R '[4] APLwi 'GetCustomerListEx' CustomerID

    1,CompanyName 2,Address 3,City 4,Region 5,PostalCode 6,Country 7,Phone8,Fax 9,Orders 10

    [5] CustomerIDioAPL CustomerID[6] Orders(1 0 1) Select (io+9)APL Orders(OrderID 1,

    OrderDate 2, OrderValue 3) without OrderDate 2[7] APL(500>1Orders) Select Orders Order Values

    below 500[8] (CustomerID APL)(APL) Select CustomerID APL Remove those

    without qualifying OrderValue[9] APL(CustomerID),APL Add CustomerID[10] APL,[io]/APL Return as a 3

    column array[11] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    The results match. The function Select is localised for the same reasons hinted in the previous example.You did investigate why this is necessary, didnt you?

    1.4.11SelectMany - Compound from 3

    This query returns all orders made in 1998 or later.

    The APL+Win function that produces the matching result is:

    ZLinq16;Linq;APL;Select;CustomerID;Orders

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    26/95

    Page 26 of 71

    [1] Projection Operators: SelectMany - Compound from 3[2] Linqwi 'Linq16'[3] 0 0def ' ZL Select R',tcnl,'[1] ZL/R '[4] APLwi 'GetCustomerListEx' CustomerID

    1,CompanyName 2,Address 3,City 4,Region 5,PostalCode 6,Country 7,Phone8,Fax 9,Orders 10

    [5] CustomerIDioAPL CustomerID[6] Orders(1 1 0) Select (io+9)APL Orders(OrderID 1,

    OrderDate 2, OrderValue 3) without OrderValue 3[7] APL(1Orders) Extract the Order

    Date UK Short date format DD/MM/YYYY[8] APL100,(100 100 10000)fiAPL~'/' Convert to

    ISO format YYYYMMDD[9] APLAPL19980101 Selection vector[10] APLAPL Select Orders Orders on or

    after 1 January 1998[11] (CustomerID APL)(APL) Select CustomerID APL Remove those

    without qualifying OrderValue[12] APL(CustomerID),APL Add CustomerID[13] APL,[io]/APL Return as a 3

    column array[14] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)[15] 0[16] This involves selection by date, a data type that APL+Win does not

    support inherently[17] As this involves a simple date comparison, it is easy to convert the

    date to ISO format & use the results as integers

    The LINQ query specifies all orders made in 1998: for APL+Win, I have interpreted this as meaning on orafterfirst of January 1998. This is necessary because APL+Win lacks the date data type and the supportingfunctions that return the constituents of a date value such as year, month, etc. Refer to lines [16]-[17] for otherdetails. Although it is quite feasible to write the C# code to return the year for this example, I felt that it wasbetter to keep the function GetCustomerListEx genericit returns the same result irrespective of the examplewhere it is used.

    1.4.12SelectMany - from Assignment

    This query returns all orders where the order total is greater than 2000.00.

    The APL+Win function that returns the result is:

    ZLinq17;Linq;APL;Select;CustomerID;Orders[1] Projection Operators: SelectMany - from Assignment[2] Linqwi 'Linq17'[3] 0 0def ' ZL Select R',tcnl,'[1] ZL/R '[4] APLwi 'GetCustomerListEx' CustomerID

    1,CompanyName 2,Address 3,City 4,Region 5,PostalCode 6,Country 7,Phone8,Fax 9,Orders 10

    [5] CustomerIDioAPL CustomerID

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    27/95

    Page 27 of 71

    [6] Orders(1 0 1) Select (io+9)APL Orders(OrderID 1,OrderDate 2, OrderValue 3) without OrderDate 2

    [7] APL(2000

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    28/95

    Page 28 of 71

    TRAIH 10574 TRAIH 10574TRAIH 10577 TRAIH 10577TRAIH 10822 TRAIH 10822WHITC 10469 WHITC 10469WHITC 10483 WHITC 10483WHITC 10504 WHITC 10504WHITC 10596 WHITC 10596WHITC 10693 WHITC 10693

    WHITC 10696 WHITC 10696WHITC 10723 WHITC 10723WHITC 10740 WHITC 10740WHITC 10861 WHITC 10861WHITC 10904 WHITC 10904WHITC 11032 WHITC 11032WHITC 11066 WHITC 11066

    A simple reminder: short results are shown within the body of the document as text and results that arelong are shown partially as a screenshotyou are invited to run the functions to see the results in full. Also,this document is best viewed with magnification, say 150%, as this renders the screenshots bigger and hencereadable with greater ease.

    1.4.14SelectMany - Indexed

    This query returns the CustomerID and OrderID for every order in the databasethe Customer list. This query

    is interesting in that it returns the results as formatted text. What if the raw results are required?

    Superficially, the results do not match! However, if you examine the results more closely, C# returns thesame result as APL+Win; the difference is in the format. The APL+Win function is:

    ZLinq19;Linq;APL;Select;CustomerID;Orders[1] Projection Operators: SelectMany - Indexed[2] Linqwi 'Linq19'[3] 0 0def ' ZL Select R',tcnl,'[1] ZL/R '[4] APLwi 'GetCustomerListEx' CustomerID

    1,CompanyName 2,Address 3,City 4,Region 5,PostalCode 6,Country 7,Phone8,Fax 9,Orders 10

    [5] CustomerIDioAPL CustomerID[6] CustomerID,+\(CustomerID)/1 Give each

    customer it own cardinal number[7] Orders(1 0 0) Select (io+9)APL Orders(OrderID 1,

    OrderDate 2, OrderValue 3) Keep OrderID only[8] (CustomerID Orders)(0Orders) Select CustomerID Orders Remove

    those without any Orders[9] APL(CustomerID),Orders Add CustomerID[10] APL,[io]/APL Return as a 2

    column array[11] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    1.5Partitioning Operators

    This group of operators splice their arguments and return subset as their result

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    29/95

    Page 29 of 71

    1.5.1Take - Simple

    This query uses Take to generate a sequence of the first three elements of an integer vector; note that in thisinstance, not only do C# LINQ and APL+Win share the jargon but the jargon has an identical meaning in bothcontexts.

    ZLinq20;Linq;APL[1] Partitioning Operators: Take - Simple

    [2] Linqwi 'Linq20'[3] APL35 4 1 3 9 8 6 7 2 0[4] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    Of course, the results match!

    Linq20LINQ APL Match?5 4 1 5 4 1 1

    1.5.2Take - Nested

    This query returns customer ID, order ID, and order date for the first three orders from customers inWashington. The sample uses Take to limit the sequence generated by the query expression to the first

    three of the orders. The hidden complication is that some customers may have zero orders.

    Linq21LINQ APL Match?

    LAZYK 10482 21/03/1997 LAZYK 10482 21/03/1997 1LAZYK 10545 22/05/1997 LAZYK 10545 22/05/1997TRAIH 10574 19/06/1997 TRAIH 10574 19/06/1997

    The function is:

    ZLinq21;Linq;APL;Select;CustomerID;Orders[1] Projection Operators: Take - Nested[2] Linqwi 'Linq21'[3] 0 0def ' ZL Select R',tcnl,'[1] ZL/R '[4] APLwi 'GetCustomerListEx' CustomerID

    1,CompanyName 2,Address 3,City 4,Region 5,PostalCode 6,Country 7,Phone8,Fax 9,Orders 10

    [5] APL(((io+4)APL)'WA')/APL Just those in theWA Region - is the fifth element

    [6] CustomerIDioAPL CustomerID[7] Orders(1 1 0) Select (io+9)APL Orders(OrderID 1,

    OrderDate 2, OrderValue 3) Keep OrderID, OrderDate only[8] (CustomerID Orders)(0Orders) Select CustomerID Orders Remove

    those without any Orders[9] APL(CustomerID),Orders Add CustomerID[10] APL,[io]/APL Return as a 3

    column array[11] APL3[io+1]APL[12] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    The APL+Win can compute other variations in this query that may also hide complications.

    1.5.2.1First two customers in Washington and all their orders

    Assuming that there are more than two customers with orders in Washington:

    [9.5] APL2APL

    [11] APL3[io+1]APL

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    30/95

    Page 30 of 71

    1.5.2.2First 3 customers in Washington and their first 5 orders

    Assuming that there are more than three customers in Washington with orders: note that some customersmay have fewer than 5 orders.

    [9.5] APL,[io]/((3,1 APL)APL)APL First 3 orders of the first3 customers in Washington APL

    [11] APL3[io+1]APL

    The interesting challenge is in coding C# for these two variations!

    1.5.3Skip - Simple

    This query uses Skip to get all but the first 4 elements of the array.

    Linq22LINQ APL Match?

    9 8 6 7 2 0 9 8 6 7 2 0 1

    The APL+Win solution:

    ZLinq22;Linq;APL[1] Partitioning Operators: Skip - Simple[2] Linqwi 'Linq22'

    [3] APL45 4 1 3 9 8 6 7 2 0[4] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    If there are fewer than four elements in the argument, the C# and APL+Win solutions return matchingresults; consider this as an exercise!

    1.5.4Skip - Nested

    This query returns all but the first two orders from customers in Washington.

    ZLinq23;Linq;APL;Select;CustomerID;Orders[1] Projection Operators: Skip - Nested[2] Linqwi 'Linq23'[3] 0 0def ' ZL Select R',tcnl,'[1] ZL/R '[4] APLwi 'GetCustomerListEx' CustomerID

    1,CompanyName 2,Address 3,City 4,Region 5,PostalCode 6,Country 7,Phone8,Fax 9,Orders 10

    [5] APL(((io+4)APL)'WA')/APL Just those in theWA Region - is the fifth element

    [6] CustomerIDioAPL CustomerID[7] Orders(1 1 0) Select (io+9)APL Orders(OrderID 1,

    OrderDate 2, OrderValue 3) Keep OrderID, OrderDate only[8] (CustomerID Orders)(0Orders) Select CustomerID Orders Remove

    those without any Orders[9] APL(CustomerID),Orders Add CustomerID[10] APL2 0,[io]/APL Return as a 3

    column array[11] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    Linq23LINQ APL Match?

    TRAIH 10574 19/06/1997 TRAIH 10574 19/06/1997 1TRAIH 10577 23/06/1997 TRAIH 10577 23/06/1997TRAIH 10822 08/01/1998 TRAIH 10822 08/01/1998WHITC 10269 31/07/1996 WHITC 10269 31/07/1996WHITC 10344 01/11/1996 WHITC 10344 01/11/1996WHITC 10469 10/03/1997 WHITC 10469 10/03/1997WHITC 10483 24/03/1997 WHITC 10483 24/03/1997WHITC 10504 11/04/1997 WHITC 10504 11/04/1997WHITC 10596 11/07/1997 WHITC 10596 11/07/1997

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    31/95

    Page 31 of 71

    WHITC 10693 06/10/1997 WHITC 10693 06/10/1997WHITC 10696 08/10/1997 WHITC 10696 08/10/1997WHITC 10723 30/10/1997 WHITC 10723 30/10/1997WHITC 10740 13/11/1997 WHITC 10740 13/11/1997WHITC 10861 30/01/1998 WHITC 10861 30/01/1998WHITC 10904 24/02/1998 WHITC 10904 24/02/1998WHITC 11032 17/04/1998 WHITC 11032 17/04/1998WHITC 11066 01/05/1998 WHITC 11066 01/05/1998

    1.5.5TakeWhile - Simple

    This query uses TakeWhile to generate return all elements from a numeric vector until elements are less than6. From an APL+Win point of view, this query is trivial.

    Linq24LINQ APL Match?

    5 4 1 3 5 4 1 3 1

    ZLinq24;Linq;APL[1] Partitioning Operators: TakeWhile - Simple[2] Linqwi 'Linq24'[3] APL5 4 1 3 9 8 6 7 2 0[4] APL(^\APL(APLAPL)-io)/APL5 4 1 3 9 8 6 7 2 0[4] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    1.5.7SkipWhile - Simple

    This query returns all of the elements of an integer vector, skipping elements until one of them is divisibleby three.

    LINQ APL Match?3 9 8 6 7 2 0 3 9 8 6 7 2 0 1

    ZLinq26;Linq;APL[1] Partitioning Operators: SkipWhile - Simple[2] Linqwi 'Linq26'[3] APL5 4 1 3 9 8 6 7 2 0[4] APL(\0=3|APL)/APL

    [5] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    17 This is missing in the links, shown at the start, at http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    32/95

    Page 32 of 71

    1.5.8SkipWhile - Indexed

    This query returns all of the elements of an integer vector, skipping elements until the element's value isless that its position in the array: remember that C# works in index origin 0.

    Linq27LINQ APL Match?

    1 3 9 8 6 7 2 0 1 3 9 8 6 7 2 0 1

    ZLinq27;Linq;APL[1] Partitioning Operators: SkipWhile - Indexed[2] Linqwi 'Linq27'[3] APL(\APL

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    33/95

    Page 33 of 71

    This result is interesting: it does not match!

    ZLinq30;Linq;APL[1] Ordering Operators: OrderBy - Simple 3[2] Linqwi 'Linq30'[3] APLwi 'GetProductListEx' ProductID ProductName Category UnitPrice

    UnitsInStock[4] APL(APL)[av(io+1)APL;][5] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    1.6.3.1Where is the difference?

    On stopping the function after line [4] and running a query to isolate the differences yields:

    The results match in terms of the number of rows. The difference lies with the character data. C# sorts theresults and passes it to APL+Win; it also passes the raw data to APL+Win. There is loss of accuracy arisingfrom the lack of support for Unicode in APL+Win; in contrast, C# uses Unicode. APL+Win is sorting the dataafter the loss of accuracy whereas it is the C# resultnot the datathat suffers the same loss.

    1.6.4OrderBy - Comparer

    This example returns a string vector sorted according to a case insensitive alphanumeric sort.

    Linq31LINQ AbAcUs aPPLE BlUeBeRrY bRaNcH cHeRry ClOvEr

    APL AbAcUs aPPLE BlUeBeRrY bRaNcH cHeRry ClOvErMatch? 1

    The APL+Win function:

    ZLinq31;Linq;APL[1] Ordering Operators - OrderBy - Comparer[2] Linqwi 'Linq31'[3] APL"aPPLE" "AbAcUs" "bRaNcH" "BlUeBeRrY" "ClOvEr" "cHeRry"[4] APLAPL[avUCase APL][5] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    34/95

    Page 34 of 71

    In order to keep the results comparable, I have not used any API calls in the APL+Win solution.

    1.6.5OrderByDescending - Simple 1

    This query returns a vector of floating point numbers sorted in descending order.

    Linq32LINQ 4.1 2.9 2.3 1.9 1.7APL 4.1 2.9 2.3 1.9 1.7

    Match? 1.0

    The function:

    ZLinq32;Linq;APL[1] Ordering Operators - OrderByDescending - Simple 1[2] Linqwi 'Linq32'[3] APL1.7 2.3 1.9 4.1 2.9[4] APLAPL[APL][5] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

    1.6.6OrderByDescending - Simple 2

    This query returns a list of products sorted by the number of units of each product that are in stock.

    The APL+Win function:

    ZLinq33;Linq;APL[1] Ordering Operators - OrderByDescending - Simple 2[2] Linqwi 'Linq33'[3] APLwi 'GetProductListEx'[4] APLAPL[(io+4)wi 'GetProductListEx'] ProductID ProductName

    Category UnitPrice UnitsInStock[5] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    1.6.7OrderByDescending - Comparer

    This query returns a vector of strings sorted alphabetically in descending order, using a case insensitivecomparison.

    Linq34LINQ ClOvEr cHeRry bRaNcH BlUeBeRrY aPPLE AbAcUsAPL ClOvEr cHeRry bRaNcH BlUeBeRrY aPPLE AbAcUs

    Match? 1

    The APL+Win function:

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    35/95

    Page 35 of 71

    ZLinq34;Linq;APL[1] Ordering Operators - OrderByDescending - Comparer[2] Linqwi 'Linq34'[3] APL"aPPLE" "AbAcUs" "bRaNcH" "BlUeBeRrY" "ClOvEr" "cHeRry"[4] APLAPL[avLCase APL][5] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

    1.6.8ThenBy - SimpleThis sample uses a compound orderby to sort a list of digits first by length of their name, and thenalphabetically.

    Linq35LINQ one six two five four nine zero eight seven threeAPL one six two five four nine zero eight seven three

    Match? 1

    ZLinq35;Linq;APL[1] Ordering Operators - ThenBy - Simple[2] Linqwi 'Linq35'[3] APL"zero" "one" "two" "three" "four" "five" "six" "seven"

    "eight" "nine"[4] APLAPL[avLCase APL][5] APLAPL[APL][6] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)

    1.6.9ThenBy - Comparer

    This sample prints an array of string values sorted first by length, then sorted alphabetically, using a case-insensitive comparison.

    ZLinq36 words;Linq;APL[1] Ordering Operators - ThenBy - Comparer[2] Linqwi 'Linq36' words[3] wordswords[avLCasewords][4] APLwords[words][5] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)[6] 0[7] Linq36 "aPPLE" "AbAcUs" "bRaNcH" "BlUeBeRrY" "ClOvEr" "cHeRry"[8] Linq36 "zero" "oNe" "TWo" "tHRee" "foUR" "FIVE" "sIx" "SEVEn"

    "eigHt" "NIne" "TEn" "HundRED"

    1.6.10ThenByDescending - Simple

    This sample uses a compound orderby to sort a list of products, first by category in ascending order, andthen by unit price in descending order.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    36/95

    Page 36 of 71

    ZLinq37;Linq;APL[1] Ordering Operators - ThenByDescending - Simple[2] Linqwi 'Linq37'[3] APLwi 'GetProductListEx'[4] APLAPL[((io+3)APL)[av ((io+2)APL) [(io+3)APL]]][5] Z('LINQ' 'APL' 'Match?'),[io-0.5]Linq APL (LinqAPL)[6] 0[7] Take it a little slower![8] APLwi 'GetProductListEx' Get the Product List[9] UnitPrice(io+3)APL UnitProce is the 4th element[10] Category(io+2)APL Category is the 3rd element

    [11] APLAPL[(UnitPrice)[avCategory[UnitPrice]]]

    1.6.11ThenByDescending - Comparer

    This sample uses an OrderBy and a ThenBy clause with a custom comparer to sort first by word length andthen by a case-insensitive descending sort of the words in an array.

    ZLinq38 words;Linq;APL[1] Ordering Operators: ThenByDescending - Comparer[2] Linqwi 'Linq38' words[3] wordswords[avLCase words][4] APLwords[words][5] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)[6] 0[7] Linq38 "aPPLE" "AbAcUs" "bRaNcH" "BlUeBeRrY" "ClOvEr" "cHeRry"[8] Linq36 "zero" "oNe" "TWo" "tHRee" "foUR" "FIVE" "sIx" "SEVEn"

    "eigHt" "NIne" "TEn" "HundRED"

    1.6.12Reverse

    This query returns a list strings from an input string vector where each element has the second letter 'i'. Theoutput list the elements in reverse order. The sample uses a query operator to gather the elements that have'i' as the second letter and then reverses the sequence using the Reverse method.

    Linq39LINQ nine eight six fiveAPL nine eight six five

    Match? 1

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    37/95

    Page 37 of 71

    ZLinq39;Linq;APL[1] Ordering Operators: ThenByDescending - Comparer[2] words"zero" "one" "two" "three" "four" "five" "six" "seven"

    "eight" "nine"[3] Linqwi 'Linq39' words[4] APL('i'=11words)/words[5] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)[6] 0

    [7] APL('i'.words)/words to pick up words with at least one 'i'anywhere

    [8] APL('io'.words)/words to pick up words with at least onesubstring 'io' anywhere

    1.7Grouping Operators

    This group of operators collates elements contiguously depending on applicable criteria.

    1.7.1GroupBy - Simple 1

    This query uses group by to partition a list of numbers by their remainder when divided by 5.

    Linq40LINQ APL Match?

    5 0 5 0 10 0 0 04 4 4 49 4 9 41 1 1 16 1 6 13 3 3 38 3 8 37 2 7 22 2 2 2

    The following function produces the matching result:

    ZLinq40;L;R;Linq;APL[1] Grouping Operators: GroupBy - Simple 1

    [2] Linqwi 'Linq40'[3] APL5 4 1 3 9 8 6 7 2 0[4] L5|APL[5] R((LL)=L)/L[6] (APL L)(RL)L APL[7] APLL APL[8] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    1.7.2GroupBy - Simple 2

    This sample partitions a vector of words into groups according to the first letter of each word.

    Linq41LINQ APL Match?

    b blueberry b blueberry 1

    b banana b bananac chimpanzee c chimpanzeec cheese c cheesea abacus a abacusa apple a apple

    ZLinq41;L;R;Linq;APL[1] Grouping Operators: GroupBy - Simple 2[2] Linqwi 'Linq41'[3] APL"blueberry" "chimpanzee" "abacus" "banana" "apple" "cheese"[4] L1APL

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    38/95

    Page 38 of 71

    [5] R((LL)=L)/L[6] (L APL) (RL)L APL[7] APLL APL[8] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    1.7.3GroupBy - Simple 3

    This sample uses group by to partition a list of products by category. Coding the C# method to return the

    result to APL+Win was nothing short of an unpleasant ordeal, given the simplicity of the query.

    The APL function:

    ZLinq42;Linq;APL;Category;SelectByCategory;Select[1] Grouping Operators - Simple 3[2] Linqwi 'Linq42' wi 'Linq42'[3] APLwi 'GetProductListEx'[4] 0 0def ' ZL Select R',tcnl,'[1] ZL/R '[5] Category(io+2)APL[6] DistinctCategory((CategoryCategory)=Category)/Category[7] SelectByCategory[io+1](DistinctCategory).Category[8] APL((DistinctCategory),SelectByCategory Select APL)[9] Z(Linq) (APL)[10] Z('APL' 'Linq' 'Match?'),[io-0.5]Z ,(LinqAPL)

    You will need to run the query in order to see the detail of the result. As an aside, this illustrates thepossibilities of created nested variables in C# in ways that make them compatible with ones in APL+Win.

    1.7.4GroupBy - Nested

    This query returns a list of each customer's orders, first by year, and then by month. It reconstructs ahierarchical data source:

    :for customer :in customers Unique:for order :in orders Recurring

    :for year in orderdate Recurring:for month in orderdate Recurring

    . process :endfor

    :endfor:endfor

    :endfor

    This query is a complicated mess. I am not going to present the result in tabular format since this isprobably impossible given the structure of the sample code. The sample reads as follows:

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    39/95

    Page 39 of 71

    publicvoid Linq43() {List customers = GetCustomerList();

    var customerOrderGroups =from c in customersselect

    new {c.CompanyName,

    YearGroups =from o in c.Ordersgroup o by o.OrderDate.Year into ygselect

    new {Year = yg.Key,MonthGroups =

    from o in yggroup o by o.OrderDate.Month into mgselectnew { Month = mg.Key, Orders = mg }

    }};

    ObjectDumper.Write(customerOrderGroups, 3);}

    Note that ObjectDumper is a class that writes the result to the console; I have not used this anywherewithin this project. The result it produces looks as follows:

    APL+Win presents the result of the query for the first customer much more meaningfully:

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    40/95

    Page 40 of 71

    This customer placed orders in June and October 1997, one (value of 8145) and two (values of 878 and330) respectively in each. The orders for 1998 must be self-evident from the above.

    This function simple brings the results and raw data from C#: feel free to render the data in tabular format.

    ZLinq43;Linq;APL[1] Grouping Operators - GroupBy - Nested

    [2] Linqwi 'Linq43'[3] APLiowi 'GetCustomerListEx'[4] LinqLinq[1;][5] See the writeup

    1.7.5GroupBy Comparer

    This query and the next one delivers the same functionality as the next one except in one respect: it does notconvert the result to uppercase. It also suffers from the same deficiencies

    Linq44LINQ APL Match?

    from from FORM 0salt last salt lastearn near earn near

    FORM

    The comparison fails since I have corrected the anomalies of the C# solution when coding the APL+Winfunction:

    ZLinq44;Linq;APL[1] Grouping Operators - GroupBy - Comparer[2] Linqwi 'Linq44'[3] APL" from " " salt " " earn " "last" "near" "FORM"[4] APL(+/^\ ' '=APL)APL[5] APL(-+/^\' '=APL)APL[6] a((aa)=a)/aLCase APL[7] b((a)LCase APL)LCase APL[8] cbb[9] APL([io+1]((c=c)/c).=c)Select APL

    [10] Z('LINQ' 'APL' 'Match?'),[io-0.5]Linq APL (LinqAPL)

    1.7.6GroupBy Comparer, Mapped

    This sample displays which elements from an input string array have the same letters. The sample usedGroupBy and an AnagramEqualityComparer class to group the elements into those with the same letters.Note the conversion to uppercase.

    The C# sample solution is deficient! In order to illustrate this I have added two more pairs of phrases tothe arguments used in the sample.

    Linq45LINQ APL Match?

    FROM FORM FROM FORM 0SALT LAST SALT LASTEARN NEAR EARN NEARAJAY AJAYASKOOLUM ASKOOLUMDEBIT CARD DEBIT CARD BAD CREDITBAD CREDIT OWLS SLOWSLOWOWLS

    The C# solution fails to allow for embedded spaces, although it does trim leading and trailing spaces,which should be inconsequential in finding anagrams.

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    41/95

    Page 41 of 71

    The C# solution also fails to cope with the case of the phrases, although it converts the resultnot theargumentsto uppercase.

    The APL+Win solution, which corrects the C# deficiencies, is:

    ZLinq45;Linq;APL

    [1] Grouping Operators - GroupBy - Comparer, Mapped[2] Linqwi 'Linq45'[3] APLUCase " from " " salt " " earn " "last" "near" "FORM" "ajay"

    "askoolum" "Debit Card" "Bad Credit" "OWLS" "slow"[4] APL(+/^\ ' '=APL)APL[5] APL(-+/^\' '=APL)APL[6] a((aa)=a)/aAPL[7] b ((a)APL)APL[8] cbb[9] APL([io+1]((c=c)/c).=c)Select APL[10] Z('LINQ' 'APL' 'Match?'),[io-0.5]Linq APL (LinqAPL)

    1.8Set Operators

    As the name implies, this group of operators apply to vectors of numbers or literals. APL+Win is naturally

    disposed to excel in this context.1.8.1Distinct - 1

    The sample creates a sequence of unique factors by using the Distinct method on the integer vector of factorsto remove duplicates.

    Linq46LINQ 2 3 5APL 2 3 5

    Match? 1

    ZLinq46;Linq;APL[1] Set Operators: Distinct - 1[2] Linqwi 'Linq46' (R2 2 3 5 5)[3] APL((RR)=R)/R

    [4] Z('LINQ' 'APL' 'Match?'),Linq APL (LinqAPL)[5] 0[6] Linq46 2 2 3 5 5 Original example[7] Linq46 9 8 7 6 2 1 2 3 9 8 7 6 5 2 3 4 5 9 0 8 71

    I have coded t he C# method to accept any arbitrary but compatible argument .

    Linq46 9 8 7 6 2 1 2 3 9 8 7 6 5 2 3 4 5 9 0 8 71LINQ 2 3 5 9 8 7 6 2 1 2 3 9 8 7 6 5 2 3 4 5 9 0 8 71APL 2 3 5

    Match? 1

    1.8.2Distinct - 2

    This query returns the unique Category names by first selecting all of the category names from theproduct list, then using Distinct to remove duplicate names.

    Linq47LINQ APL Match?

    Beverages Beverages 1Condiments CondimentsProduce Produce

    Meat/Poultry Meat/PoultrySeafood SeafoodDairy Products Dairy ProductsConfections Confections

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    42/95

    Page 42 of 71

    Grains/Cereals Grains/Cereals

    The APL+Win function:

    ZLinq47;Linq;APL[1] Set Operators: Distinct - 2[2] Linqwi 'Linq47'[3] APL(io+2)wi 'GetProductListEx' ProductID ProductName Category

    UnitPrice UnitsInStock[4] APL((APLAPL)=APL)/APL[5] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    1.8.3Union - 1

    This query returns the unique elements of two integer arrays. The sample uses the Union method tocreate a sequence that is a union of the two integer arrays with duplicate elements removed.

    ZLinq48;L;R;Linq;APL[1] Set Operators: Union - 1[2] L(2?10)?15 With possible replication[3] R(2?10)?23 With possible replication[4] Linqwi 'Linq48' L R[5] L((LL)=L)/L[6] R((RR)=R)/R[7] APLL,R~L[8] Z('L' 'R' 'LINQ' 'APL' 'Match?'),L R Linq APL (LinqAPL)

    This function is coded to use random arguments; therefore, it will return a different result simply becausethe argument is different.

    1.8.4Union - 2

    This query returns unique letters from Product and Customer names. The sample creates a sequence ofproduct first characters, a sequence of customer first characters, and then joins the two sets by using Union tomerge them and remove duplicates.

    Linq49

    LINQ APL Match?

    C C 1

    A A

    G G

    U UN N

    M M

    I I

    Q Q

    K K

    T T

    P P

    S S

    R R

    ZLinq49;L;R;Linq;APL

    [1] Set Operators: Union - 2

    [2] Linqwi 'Linq49'

    [3] (ProductID ProductName Category UnitPriceUnitsInStock) ( CustomerID CompanyNameAddress City Region PostalCode Country PhoneFax Orders[])

    [4] L1(io+1)wi 'GetProductListEx'

    [5] R1(io+1)wi 'GetCustomerListEx'

    [6] L((LL)=L)/L

    [7] R((RR)=R)/R

    [8] APLL,R~L

    [9] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL(LinqAPL)

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    43/95

    Page 43 of 71

    B B

    J J

    Z Z

    V V

    F F

    E E

    W W

    L LO O

    D D

    H H

    1.8.5Intersect - 1

    This query returns a list of numbers that are common to two integer vectors. The sample uses Intersect tocreate one sequence that contains the common values shared by vectors.

    Linq50L 3 5 13 0 10 6 4 8R 12 2 2 22 9 4 13 21 8LINQ 13 4 8APL 13 4 8

    Match? 1

    The APL+Win function :

    ZLinq50;L;R;Linq;APL

    [1] Set Operators: Intersect - 1[2] L(2?10)?15 With possible replication[3] R(2?10)?23 With possible replication[4] Linqwi 'Linq50' L R[5] APL(LR)/L[6] APL((APLAPL)=APL)/APL[7] Z('L' 'R' 'LINQ' 'APL' 'Match?'),L R Linq APL (Linq-APL)[8] 0[9] (L R)(0 2 4 5 6 8 9) (1 3 5 7 8)

    This function generates its arguments randonmly and uses each such argument and passes the sameargument to the C# method. The original arguments uses in the sample are shown in line [9].

    1.8.6Intersect - 2

    This query returns the letters that are both the first letter of a Product name and the first letter of aCustomer name. The sample uses query statements to create two sequence - the first letters of Productnames and the first letter of Customer names, then uses Intersect to create a sequence of letters common toboth.

    Linq51

    LINQ APL Match?

    C C 1

    A AG G

    N N

    M M

    I I

    Q Q

    K K

    T T

    P P

    S S

    R R

    ZLinq51;L;R;Linq;APL

    [1] Set Operators: Intersect - 2

    [2] Linqwi 'Linq51'

    [3] (ProductID ProductName Category UnitPriceUnitsInStock) ( CustomerID CompanyNameAddress City Region PostalCode Country PhoneFax Orders[])

    [4] L1(io+1)wi 'GetProductListEx'

    [5] R1(io+1)wi 'GetCustomerListEx'

    [6] APL(LR)/L

    [7] APL((APLAPL)=APL)/APL

    [8] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL(LinqAPL)

  • 8/22/2019 19525586 Linq to Objects101Samples C to AplWin

    44/95

    Page 44 of 71

    B B

    V V

    F F

    E E

    W W

    L L

    O O

    1.8.7Except - 1

    This query returns numbers that are in one integer array, but not another. The sample uses Except to create asequence that contains the values from numbersA that are not also in numbersB.

    Linq52L 9 11 7 0 3 12 8R 12 2 18 22 0 19 5LINQ 9 11 7 3 8APL 9 11 7 3 8

    Match? 1

    ZLinq52;L;R;Linq;APL[1] Set Operators: Except 1[2] L(2?10)?15 With possible replication

    [3] R(2?10)?23 With possible replication[4] Linqwi 'Linq52' L R[5] L((LL)=L)/L[6] APL(~LR)/L[7] Z('L' 'R' 'LINQ' 'APL' 'Match?'),L R Linq APL (LinqAPL)[8] 0[9] (L R)(0 2 4 5 6 8 9)(1 3 5 7 8)

    1.8.8Except - 2

    This query returns the first character of product names that are not also the first character of customer names.After getting the first characters of product and customer names using query expressions, the sample usesExcept to create a sequence of product characters that doesn't include first characters of customer names.

    Linq53

    LINQ APL Match?U U 1J JZ Z

    ZLinq53;L;R;Linq;APL[1] Set Operators: Except - 2[2] Linqwi 'Linq53'[3] (ProductID ProductName Category UnitPrice UnitsInStock) ( CustomerID

    CompanyName Address City Region PostalCode Country Phone Fax Orders[])[4] L1(io+1)wi 'GetProductListEx'[5] R1(io+1)wi 'GetCustomerListEx'[6] L((LL)=L)/L[7] APL(~LR)/L[8] Z('LINQ' 'APL' 'Match?'),[io-0.5] Linq APL (LinqAPL)

    1.9Conver