interleave/join strings

General APL language issues

interleave/join strings

Postby alexeyv on Sat Jan 14, 2017 6:27 pm

Hi,

What is the best way to join strings? For example given an array of strings, how to create one string with spaces between them?

I came to this solution:
Code: Select all
S←'this' 'is' 'a' 'sentence'
¯1↓∊(,[1.5]S),' '
┌→─────────────────┐
│this is a sentence│
└──────────────────┘


Is there more elegant way I can't see ?
alexeyv
 
Posts: 56
Joined: Tue Nov 17, 2015 4:18 pm

Re: interleave/join strings

Postby Veli-Matti on Sat Jan 14, 2017 7:09 pm

Hi,
the solutions for this specific purpose I have been using lately are either
      1↓↑,/,' ',⍪S

or
      1↓↑,/,' ',⍤0⊢S


-Veli-Matti
Veli-Matti
 
Posts: 93
Joined: Sat Nov 28, 2009 3:12 pm

Re: interleave/join strings

Postby Veli-Matti on Sat Jan 14, 2017 8:12 pm

For your amusement: testing several approaches with cmpx when using single character separator and a little bit longer nested vector:
      D←' ' ⋄ S←12345⍴S
D{1↓↑,/,⍺,⍤0⊢⍵}S → 1.0E¯3 | 0% ⎕⎕⎕⎕⎕⎕
D{1↓↑,/,⍺(,⍤0)⍵}S → 1.0E¯3 | +3% ⎕⎕⎕⎕⎕⎕⎕
D{1↓↑,/,⍺∘,⍤0⊢⍵}S → 5.3E¯3 | +427% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{1↓∊⍺∘,⍤0⊢⍵}S → 6.3E¯3 | +522% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{1↓↑,/,⍺,⍪⍵}S → 1.1E¯3 | +9% ⎕⎕⎕⎕⎕⎕⎕
D{1↓∊⍺,¨⍵}S → 2.8E¯3 | +176% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{¯1↓↑,/,⍵,[1.1]⍺}S → 1.0E¯3 | 0% ⎕⎕⎕⎕⎕⎕
D{¯1↓∊(,[1.5]⍵),⍺}S → 2.1E¯3 | +109% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕

and with a vector separator:
      D←'","'
D{(⍴⍺)↓↑,/,(⊂⍺),⍤0⊢⍵}S → 1.1E¯3 | 0% ⎕⎕⎕⎕⎕
D{(≢⍺)↓↑,/,(⊂⍺)(,⍤0)⍵}S → 1.2E¯3 | +8% ⎕⎕⎕⎕⎕
D{(⍴⍺)↓↑,/,⍺∘,⍤0⊢⍵}S → 7.0E¯3 | +557% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{(⍴⍺)↓∊⍺∘,⍤0⊢⍵}S → 9.1E¯3 | +751% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{(⍴⍺)↓↑,/,(⊂⍺),⍪⍵}S → 1.1E¯3 | +5% ⎕⎕⎕⎕⎕
D{(⍴⍺)↓∊(⊂⍺),¨⍵}S → 2.5E¯3 | +134% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{(-⍴⍺)↓↑,/,⍵,[1.1]⊂⍺}S → 1.1E¯3 | 0% ⎕⎕⎕⎕⎕
D{(-⍴⍺)↓∊(,[1.5]⍵),⊂⍺}S → 2.1E¯3 | +97% ⎕⎕⎕⎕⎕⎕⎕⎕⎕


There are remarkable differences with just small code changes.

-Veli-Matti
Veli-Matti
 
Posts: 93
Joined: Sat Nov 28, 2009 3:12 pm

Re: interleave/join strings

Postby petermsiegel on Sat Jan 14, 2017 9:56 pm

Interesting.
I expected {1↓⊃,/,⍺,⍤0⊢⍵} to slightly exceed the performance of {1↓↑,/,⍺,⍤0⊢⍵}, your fastest, on my Macbook Pro, but it ran identically in my tests. I always used {1↓∊⍺,¨⍵}, since it "appears" to me to be algorithmically the simplest, but, given the performance numbers, perhaps not.
petermsiegel
 
Posts: 141
Joined: Thu Nov 11, 2010 11:04 pm

Re: interleave/join strings

Postby Phil Last on Sat Jan 14, 2017 11:24 pm

Not surprising that those using enlist are significantly slower than their counterparts using catenate reduction. The former was always much slower from the outset while the latter has had a number of speed-ups over the years.

I've never encountered a single situation where enlist even suggests itself as being a good solution given that we almost always know the structure of the data we're dealing with.

A sledgehammer of a function if ever there was one.

As to simplifying a list of strings I've always found
      1↓⊃,/⍺∘,¨⍵
to be the best and was surprised not to see it in Veli-Matti's list.
User avatar
Phil Last
 
Posts: 628
Joined: Thu Jun 18, 2009 6:29 pm
Location: Wessex

Re: interleave/join strings

Postby petermsiegel on Sun Jan 15, 2017 1:23 am

Enlist ∊ on the left seems to add an 8-11% slowdown compared with catenate-based code (depending on what's to its right), so other parts of the code (the first/right-most catenation) in Veli-Matti's examples dominate the results. As always, real performance may depend on bigger fish.
petermsiegel
 
Posts: 141
Joined: Thu Nov 11, 2010 11:04 pm

Re: interleave/join strings

Postby Veli-Matti on Sun Jan 15, 2017 10:35 am

There are so many factors when deciding the 'best' idiom for any task. If you know beforehand that the argument is nested vector, the
      ↑,/
idiom is the fastest way around (that is, if Roger hasn't invented something under the bonnet lately..).

Just for amusement I run some tests (v15/Unicode, 32-bit, Win10).
First, pure idioms with scalar separator (' ') and short argument ('this' 'is' 'a' 'sentence'):

      1↓↑,/,(⊂D),⍤0⊢V  → 1.1E¯6 |    0% ⎕⎕⎕⎕⎕⎕                                  
1↓↑,/,(⊂D)(,⍤0)V → 1.1E¯6 | +4% ⎕⎕⎕⎕⎕⎕⎕
¯1↓↑,/,V,[1.1]⊂D → 1.0E¯6 | -4% ⎕⎕⎕⎕⎕⎕
1↓↑,/,(⊂D),⍪V → 1.0E¯6 | -6% ⎕⎕⎕⎕⎕⎕
1↓↑,/,D∘,⍤0⊢V → 6.5E¯6 | +510% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
1↓∊D∘,⍤0⊢V → 6.8E¯6 | +541% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
1↓↑,/D∘,¨V → 1.7E¯6 | +56% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
1↓∊(⊂D),¨V → 1.7E¯6 | +62% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
¯1↓∊(,[1.5]V),⊂D → 1.8E¯6 | +70% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
↑{⍺,D,⍵}/V → 2.1E¯6 | +92% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕


Next test with the same arguments, but the sentences in dfns
      D{1↓↑,/,(⊂⍺),⍤0⊢⍵}V  → 1.4E¯6 |    0% ⎕⎕⎕⎕⎕⎕⎕                                 
D{1↓↑,/,(⊂⍺)(,⍤0)⍵}V → 1.4E¯6 | +4% ⎕⎕⎕⎕⎕⎕⎕⎕
D{¯1↓↑,/,⍵,[1.1]⊂⍺}V → 1.3E¯6 | -2% ⎕⎕⎕⎕⎕⎕⎕
D{1↓↑,/,(⊂⍺),⍪⍵}V → 1.3E¯6 | -7% ⎕⎕⎕⎕⎕⎕⎕
D{1↓↑,/,⍺∘,⍤0⊢⍵}V → 6.8E¯6 | +398% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{1↓∊⍺∘,⍤0⊢⍵}V → 7.3E¯6 | +435% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{1↓↑,/⍺∘,¨⍵}V → 1.9E¯6 | +42% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{1↓∊(⊂⍺),¨⍵}V → 2.0E¯6 | +47% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
D{¯1↓∊(,[1.5]⍵),⊂⍺}V → 2.0E¯6 | +48% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
{↑{⍺,D,⍵}/⍵}V → 2.3E¯6 | +70% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕


Then scalar separator with a longish argument (12345<reshape>'this' 'is' 'a' 'sentence')

      D{1↓↑,/,(⊂⍺),⍤0⊢⍵}V  → 1.0E¯3 |     0%                                         
D{1↓↑,/,(⊂⍺)(,⍤0)⍵}V → 1.0E¯3 | 0%
D{¯1↓↑,/,⍵,[1.1]⊂⍺}V → 1.0E¯3 | +1%
D{1↓↑,/,(⊂⍺),⍪⍵}V → 1.1E¯3 | +6%
D{1↓↑,/,⍺∘,⍤0⊢⍵}V → 5.3E¯3 | +419% ⎕⎕
D{1↓∊⍺∘,⍤0⊢⍵}V → 6.3E¯3 | +513% ⎕⎕⎕
D{1↓↑,/⍺∘,¨⍵}V → 3.2E¯3 | +208% ⎕
D{1↓∊(⊂⍺),¨⍵}V → 2.8E¯3 | +171% ⎕
D{¯1↓∊(,[1.5]⍵),⊂⍺}V → 2.1E¯3 | +105% ⎕
{↑{⍺,D,⍵}/⍵}V → 9.5E¯2 | +9187% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕


Last, vector separator ('","') with long argument
      D{(⍴⍺)↓↑,/,(⊂⍺),⍤0⊢⍵}S  → 1.0E¯3 |      0%                                         
D{(≢⍺)↓↑,/,(⊂⍺)(,⍤0)⍵}S → 1.0E¯3 | -2%
D{(-⍴⍺)↓↑,/,⍵,[1.1]⊂⍺}S → 1.0E¯3 | -2%
D{(⍴⍺)↓↑,/,(⊂⍺),⍪⍵}S → 1.1E¯3 | +5%
D{(⍴⍺)↓↑,/⍺∘,¨⍵}S → 2.8E¯3 | +171% ⎕
D{(⍴⍺)↓∊(⊂⍺),¨⍵}S → 2.5E¯3 | +143% ⎕
D{(⍴⍺)↓↑,/,⍺∘,⍤0⊢⍵}S → 7.1E¯3 | +577% ⎕⎕
D{(⍴⍺)↓∊⍺∘,⍤0⊢⍵}S → 9.0E¯3 | +758% ⎕⎕⎕
D{(-⍴⍺)↓∊(,[1.5]⍵),⊂⍺}S → 2.1E¯3 | +100% ⎕
{↑{⍺,D,⍵}/⍵}S → 1.3E¯1 | +12525% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕


-Veli-Matti

PS. Phil, I didn't forget that idiom, I just feel that composition is as avoidable as enlist :)
Veli-Matti
 
Posts: 93
Joined: Sat Nov 28, 2009 3:12 pm

Re: interleave/join strings

Postby Morten|Dyalog on Sun Jan 15, 2017 10:38 am

OK, looks like we (Dyalog) have some work to do. Thanks for pointing this out!

Code: Select all
      5↑txt←(?100⍴10)⍴¨⊂⎕A
 ABCDEFGH  ABCDEFG  ABCDEFG  A  ABCDEF
      cmpx '⊃,/'' '',¨txt' '∊'' '',¨txt' '{n←1+≢¨⍵ ⋄ (,n∘.≥⍳⌈/n)/,'' '',↑⍵}txt'
  ⊃,/' ',¨txt                        → 1.9E¯5 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕   
  ∊' ',¨txt                          → 2.1E¯5 | +12% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  {n←1+≢¨⍵ ⋄ (,n∘.≥⍳⌈/n)/,' ',↑⍵}txt  → 7.1E¯6 | -63% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕                           
User avatar
Morten|Dyalog
 
Posts: 453
Joined: Tue Sep 09, 2008 3:52 pm

Re: interleave/join strings

Postby Veli-Matti on Sun Jan 15, 2017 11:12 am

..running Morten's charming vintage idiom with the same testbed as the earlier ones (with the modern []ML :) ):
      ' ' ∆tst0 12345⍴'this' 'is' 'a' 'sentence'  
¯1↓↑,/,V,[1.1]⊂D → 9.8E¯4 | 0%
1↓↑,/,(⊂D),⍤0⊢V → 9.8E¯4 | 0%
1↓↑,/,(⊂D)(,⍤0)V → 1.1E¯3 | +12%
1↓↑,/,(⊂D),⍪V → 1.1E¯3 | +12%
¯1↓∊(,[1.5]V),⊂D → 2.1E¯3 | +112% ⎕
1↓(,n∘.≥⍳⌈/n←1+≢¨V)/,D,⊃V → 2.6E¯3 | +163% ⎕
1↓∊(⊂D),¨V → 2.7E¯3 | +174% ⎕
1↓↑,/D∘,¨V → 3.2E¯3 | +225% ⎕
1↓↑,/,D∘,⍤0⊢V → 5.1E¯3 | +424% ⎕⎕
1↓∊D∘,⍤0⊢V → 6.1E¯3 | +524% ⎕⎕⎕
↑{⍺,D,⍵}/V → 9.2E¯2 | +9363% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕


-wm
Veli-Matti
 
Posts: 93
Joined: Sat Nov 28, 2009 3:12 pm

Re: interleave/join strings

Postby Veli-Matti on Sun Jan 15, 2017 11:18 am

Ouch! There was some unnecessary discloses included. When they are removed, the rank idioms seem to be the quickest ones:
      1↓↑,/,D,⍤0⊢V              → 9.8E¯4 |     0%                                         
1↓↑,/,D(,⍤0)V → 1.1E¯3 | +12%
¯1↓↑,/,V,[1.1]D → 1.6E¯3 | +62% ⎕
1↓↑,/,D,⍪V → 1.2E¯3 | +24% ⎕
etc..

-wm
Veli-Matti
 
Posts: 93
Joined: Sat Nov 28, 2009 3:12 pm

Next

Return to Language

Who is online

Users browsing this forum: No registered users and 1 guest