mboost-dp1

Hvem har lært nok Java 8 til at kunne skrive ulæselig kode?


Gå til bund
Gravatar #1 - arne_v
31. aug. 2023 14:14
Fra tråd på LinkedIn.

Problem:

String s = "Sunset glow on the horizon";

lav en ny string med de bogstaver fra s som kun findes 1 gang i strengen.

Svaret er "uglwriz".

I tråden var der noget nydeligt kode med 2 for løkker som enhver nogenlunde udvikler der har set et curly bracket sprog før kunne læse og forstå.

Men ved brug af Java 8 features må det kunne laves som en enkelt statement.

String s2 = ?;

Nogle gode bud?

Jeg har en ikke køn løsning.
Gravatar #2 - arne_v
31. aug. 2023 15:23
#1

Som nemmere opvarmnings øvelse kan man lave den i C#.
Gravatar #3 - larsp
1. sep. 2023 04:27
Python:

Her er en oneliner, der lider lidt under af two .lower() kald:

s = "Sunset glow on the horizon"
s2 = "".join([c for c in s.lower() if s.lower().count(c) == 1])
print(s2)


Men ovenstående er O(n2), her er en der er O(n):


from collections import OrderedDict
s = "Sunset glow on the horizon"
d = OrderedDict()
for c in s.lower():
. d[c] = d.get(c, 0) + 1
s2 = "".join([k for k, v in d.items() if v == 1])
print(s2)


Gravatar #4 - larsp
1. sep. 2023 05:13
C

Forbavsende bøvlet...



#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main()
{
const char *s = "Sunset glow on the horizon";
int frqs[26] = {0}; // 'z' - 'a' + 1 = 26
int len = strlen(s);

for (int i = 0; i < len; i++) {
char c = tolower(s[i]);
if (c >= 'a' && c <= 'z') {
frqs[c - 'a'] += 1;
}
}

for (int i = 0; i < len; i++) {
char c = tolower(s[i]);
if (c >= 'a' && c <= 'z' && frqs[c - 'a'] == 1) {
printf("%c", c);
frqs[c - 'a'] = 0;
}
}
printf("\n");
return 0;
}

Gravatar #5 - arne_v
1. sep. 2023 14:55
#4

Det kan næppe laves som one-liner i C.

Gravatar #6 - Claus Jørgensen
1. sep. 2023 22:30
Swift:


let s = "Sunset glow on the horizon"

let s2 = String(s.lowercased().reduce(into: [Character: Int](), { $0[$1] = ($0[$1] ?? 0) + 1 }).filter { $0.value == 1 }.map { $0.key })


Hvis jeg skulle gætte, vil jeg tænke at man kan gøre det samme i Java 8 med Stream.reduce?
Gravatar #7 - Claus Jørgensen
1. sep. 2023 23:24
Java 8


String s = "Sunset glow on the horizon";

String s2 = s.chars()
.mapToObj(c -> Character.toLowerCase((char)c))
.collect(Collectors.groupingBy(c -> c, LinkedHashMap::new, Collectors.counting()))
.entrySet()
.stream()
.filter(e -> e.getValue() == 1)
.map(e -> "" + e.getKey())
.collect(Collectors.joining());

System.out.println(s2); // uglwriz
Gravatar #8 - arne_v
1. sep. 2023 23:31
#6

Det er jo indlysende Stream man skal have gang i for at kunne lave en one-liner.

Min løsning bruger dog ikke reduce men collect med Collectors.groupingBy (ligesom min C# udgave bruger GroupBy).

Men der kan sagtens være bedre løsninger.
Gravatar #9 - arne_v
1. sep. 2023 23:35
#7

Det er meget tæt på min kode.

Jeg endte med:


String s = "Sunset glow on the horizon";
String s2 = s.replace(" ", "").toLowerCase().chars()
.boxed().collect(Collectors.groupingBy(c -> c, LinkedHashMap::new, Collectors.counting()))
.entrySet().stream().filter(e -> e.getValue() == 1)
.map(e -> Character.toString((int)e.getKey())).collect(Collectors.joining());
System.out.println(s2);
Gravatar #10 - arne_v
1. sep. 2023 23:44
#4

Er du ikke lidt nærig med byte'ne?

:-)


#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>

int main()
{
const char *s = "Sunset glow on the horizon";
int frqs[1 << CHAR_BIT] = { 0 };
int len = strlen(s);

for (int i = 0; i < len; i++) {
char c = tolower(s[i]);
if (c >= 'a' && c <= 'z') {
frqs[c] += 1;
}
}

for (int i = 0; i < len; i++) {
char c = tolower(s[i]);
if (c >= 'a' && c <= 'z' && frqs[c] == 1) {
printf("%c", c);
frqs[c] = 0;
}
}
printf("\n");
return 0;
}


Den kode spilder 230 bytes. Men ...
Gravatar #11 - arne_v
2. sep. 2023 00:17
#10

Og:

c >= 'a' && c <= 'z'

burde nok være:

isalpha(c)

i håb om at locale ville få danske bogstaver til at virke.
Gravatar #12 - larsp
2. sep. 2023 08:51
arne_v (10) skrev:
Den kode spilder 230 bytes. Men ...

Den spilder 230 * sizeof(int) på en 8-bit char platform :) Ja, man kunne supportere extended code page på den måde, men det er jo ikke unicode og derfor lidt meningsløst...

Det er jo et typisk alderdomstegn for C. Mangel på (nem) unicode support. Alle de andre løsninger listet her æder unicode til morgenmad, tænker jeg.

Men, mon ikke C koden er den hurtigste af løsningerne indtil videre ;)
Gravatar #13 - Claus Jørgensen
2. sep. 2023 11:54
#9

Din kode er hvordan jeg forsøgte at skrive det til at begynde med, men kunne ikke få det til at kompilere

Men jeg har så heller ikke rigtigt arbejdet i Java i næsten 20 år :P
Gravatar #14 - Claus Jørgensen
2. sep. 2023 11:56
#12

Både Arne og migselv brugte chars() og ikke codepoints(), så det ville ikke virke med alle unicode characters.
Gravatar #15 - arne_v
2. sep. 2023 13:01
larsp (12) skrev:
arne_v (10) skrev:
Den kode spilder 230 bytes. Men ...

Den spilder 230 * sizeof(int) på en 8-bit char platform :)


Ups. 230 int's.

larsp (12) skrev:

Ja, man kunne supportere extended code page på den måde, men det er jo ikke unicode og derfor lidt meningsløst...


Man undgår -'a' konstruktionen og man kan understøtte ikke fortløbende bogstaver.

Ikke fortløbende bogstaver i 8 bit vil være ISO-8859-whatever.

Algoritmen er ikke UTF-8 venlig.

Man kunne ret nemt lave den samme algoritme med wchar_t og dermed få unicode support.

larsp (12) skrev:

Det er jo et typisk alderdomstegn for C. Mangel på (nem) unicode support. Alle de andre løsninger listet her æder unicode til morgenmad, tænker jeg.


Java char er 16 bit. Så ja.

larsp (12) skrev:

Men, mon ikke C koden er den hurtigste af løsningerne indtil videre ;)


Sikkert.
Gravatar #16 - arne_v
2. sep. 2023 13:03
Claus Jørgensen (14) skrev:

Både Arne og migselv brugte chars() og ikke codepoints(), så det ville ikke virke med alle unicode characters.


Sandt nok.

Men det virker med BMP.

Og BMP er normalt "godt nok".


Gravatar #17 - arne_v
2. sep. 2023 13:13
arne_v (15) skrev:

Man kunne ret nemt lave den samme algoritme med wchar_t og dermed få unicode support.



#include <stdio.h>
#include <string.h>
#include <wctype.h>
#include <limits.h>

int main()
{
const wchar_t *s = L"Sunset glow on the horizon";
int frqs[sizeof(wchar_t) * (1 << CHAR_BIT)] = { 0 };
int len = wcslen(s);

for (int i = 0; i < len; i++) {
wchar_t c = towlower(s[i]);
if (iswalpha(c)) {
frqs[c] += 1;
}
}

for (int i = 0; i < len; i++) {
wchar_t c = towlower(s[i]);
if (iswalpha(c) && frqs[c] == 1) {
printf("%c", c);
frqs[c] = 0;
}
}
printf("\n");
return 0;
}



Unicode BMP support! :-)
Gravatar #18 - larsp
3. sep. 2023 05:03
#17 Interessant. Jeg prøvede koden og måtte tilføje og rette:

#include <locale.h>
#include <stddef.h>
#include <wchar.h>

setlocale(LC_ALL, "");

printf("%lc", c);

for at få det til at virke med nogle æøåer.

Algoritmen falder iøvrigt ... fuldstændigt ... fra hinanden hvis man fikser denne linje:
int frqs[1 << (sizeof(wchar_t) * CHAR_BIT)] = { 0 };

wchar_t er 4 bytes bred hos mig, så vi snupper lige 2^32 fra stakken ...
Gravatar #19 - arne_v
3. sep. 2023 12:30
larsp (18) skrev:


setlocale(LC_ALL, "");



Default locale er C og den kan ikke så meget.

larsp (18) skrev:

Algoritmen falder iøvrigt ... fuldstændigt ... fra hinanden hvis man fikser denne linje:
int frqs[1 << (sizeof(wchar_t) * CHAR_BIT)] = { 0 };

wchar_t er 4 bytes bred hos mig, så vi snupper lige 2^32 fra stakken ...


Ups.

Jeg antog at wchar_t var 16 bit.

Hvilket var en uheldig antagelse, da C naturligvis ikke garanterer dette.

Hvilken compiler/platform bruger 32 bit wchar_t?


Gravatar #20 - larsp
3. sep. 2023 17:33
arne_v (19) skrev:
Hvilken compiler/platform bruger 32 bit wchar_t?

printf("%ld\n", sizeof(wchar_t)); // printer: 4


Det er en Ubuntu 22.04.3 med kernel: 5.15.0-79-generic x86_64, gcc: 11.4.0
Gravatar #21 - arne_v
3. sep. 2023 18:27
larsp (20) skrev:

Det er en Ubuntu 22.04.3 med kernel: 5.15.0-79-generic x86_64, gcc: 11.4.0


Jeg testede lige lidt.

Det ser faktisk ud som om wchar_t er 4 på alle platforme undtagen Windows (både mit Linux sytsem og mit VMS system har 4).

Det shift var ikke en god ide.

GCC har -fshort-wchar som vil ændre til 2 på ikke-Windows platforme. Men ingen wcs funktioner virker med det, så det er at skyde sig selv i foden.
Gravatar #22 - Claus Jørgensen
3. sep. 2023 18:48
Er hele ideen med type definitions som wchar_t ikke at man kan ignorer størrelse på typerne?

Gravatar #23 - arne_v
3. sep. 2023 19:16
#22

Jo men ...

C standarden siger at:


wchar_t

which is an integer type whose range of values can represent distinct codes for all
members of the largest extended character set specified among the supported locales; the null character shall have the code value zero


så C garanterer at et valid tegn i en locale kan opbaveres i wchar_t.

Men C udspecificerer ikke hvilke tegn/locale der skal understøttes.

Så wchar_t kan være næsten hvad som helst.

Ofte er dfet ligegyldigt hvad det er, men i det her tilfælde ville jeg gerne have antal mulige værdier.

Så jeg forsøgte med:

antal char i en wchar_t * (1 << amtal bits i en char)

og fejlede fordi der er ikke nogen upper limit på størrelse og mange platforme har bare valgt 4.

Næste forsøg er WCHAR_MAX. Hvis de var bare en lille smule brugervenlige ville den indeholde den højeste brugbare værdi og ikke højeste værdi der kan gemmes i den type integer som wchar_t er.

No luck. 2147483647.
Gravatar #24 - larsp
3. sep. 2023 20:19
Ang. opgaven i #1 er pythons OrderedDict vel den noget nær perfekte datastruktur og med få linjer kode kan man således løse opgaven med glimrende performance i python. For at kunne følge med i C, i unicode, vil man være nød til at skrive et ret omstændeligt program, med risiko for alle mulige fejl, hvorefter C programmet nok vil tage føringen i performance. Det er jo et ret sigende eksempel på sprogenes styrker og svagheder.

De andre onelinere herover er totalt ulæselige for mig, haha ... "{ $0[$1] = ($0[$1] ?? 0) + 1 }" what??

Kan vi mon få en løsning i Rust :)
Gravatar #25 - arne_v
3. sep. 2023 23:43
larsp (24) skrev:
For at kunne følge med i C, i unicode, vil man være nød til at skrive et ret omstændeligt program, med risiko for alle mulige fejl,


Problemet er som altid at C ikke definerer tingene præcist men lader meget være op til implementationen.

C99 har:

const wchar_t *s = L"Sunset glow on the horizon";

og streng funktioner wcslen, towlower og iswalpha.

Men standarden garanterer kun at wchar_t kan indeholde alle tegn som den pågældende implementation understøtter.

Hvis makro __STDC_ISO_10646__ er defineret skal værdierne være Unicode.

Praksis synes at være at wchar_t på Windows er UTF-16 og på ikke-Windows er UTF-32.

Der er ikke nogen god måde at få antal mulige værdier. På Windows kunne man forsigtigt antage 65536 og på ikke-Windows kunne man antage enten totale antal unicode værdier 149186 eller hvis man antager BMP 65536.

C11 har tilføjet:

const char16_t *s = u"Sunset glow on the horizon";
const char32_t *s = U"Sunset glow on the horizon";

men ingen funktioner.

Hvis henholdsvis __STDC_UTF_16__ og __STDC_UTF_32__ er defineret skal de indeholde UTF-16 og UTF-32.

Og i praksis gør de.

C23 kræver at de er UTF-16 og UTF-32.

Gravatar #26 - arne_v
3. sep. 2023 23:50
#C

Jeg tror iøvrigt at algoritmen med frqs har yderligere en komplikation.

Hvis char eller wchar_t default er signed vil man få negative værdier for nogle tegn.

Så længe man bruger a..z test og et superset af ASCII er det OK. Men med support for nationale tegn eller et tegnsæt som ikke er et superset af ASCII (EBCDIC) har man et potentielt problem.

32 bit wchar_t er dog sikker - 149186 er ikke stort nok til at gå i negativ.

Gravatar #27 - Claus Jørgensen
4. sep. 2023 09:31
larsp (24) skrev:
De andre onelinere herover er totalt ulæselige for mig, haha ... "{ $0[$1] = ($0[$1] ?? 0) + 1 }" what??


$0 = første argument i en closure
$1 = næste argument i en closure

Kunne også være skrevet som

{ d[c] = (d[c] ?? 0) + 1 }

Og I Swift giver et key access på dictionary en optional tilbage, du ved, i tilfælde af værdien ikke findes. Så derfor skal vi lige bruge en default værdi (0)

Det er det samme du gør her med d.get(c, 0) i din oprindelige kode.
Gravatar #28 - arne_v
5. sep. 2023 00:35
larsp (24) skrev:

Kan vi mon få en løsning i Rust :)


Jeg kan ikke klare en one linier.

Men noget simpel kode:


fn main() {
let s = "Sunset glow on the horizon";
let mut res = String::from("");
for c in s.to_lowercase().chars() {
if s.to_lowercase().matches(c).count() == 1 {
res.push(c)
}
}
println!("{}", res);
}


Gravatar #29 - larsp
5. sep. 2023 06:06
#27 Aha, giver mening. $0 og $1 minder om parametre i bash funktioner :P

#28 Meget ligefrem kode

Ang. OrderedDict i Python, det er åbenbart ophøjet til krav at man kan forvente {} at bevare insertion order fra Python 3.7 og frem. Jeg synes stadig det er på sin plads at bede om OrderedDict eksplicit hvis man har brug for den egenskab.
Gravatar #30 - arne_v
5. sep. 2023 13:28
larsp (29) skrev:

#28 Meget ligefrem kode


Kender man ikke et sprog specielt godt, så bliver kode ofte meget ligefrem.

larsp (29) skrev:

Ang. OrderedDict i Python, det er åbenbart ophøjet til krav at man kan forvente {} at bevare insertion order fra Python 3.7 og frem. Jeg synes stadig det er på sin plads at bede om OrderedDict eksplicit hvis man har brug for den egenskab.


Enten eksplicit valg af OrderedDict eller et test på Python version.
Gravatar #31 - arne_v
8. sep. 2023 12:18
#3

Et vigtigt element i Python løsningerne er hvad jeg kalder "den vandrette for løkke". Konstruktionen har sikkert et rigtigt navn i Python.

Men det pussige er at det er en meget gammel konstruktion.

Fortran har den (under navnet "implied do loop").


program horfor
integer*4 ia(5)
integer*4 i
data (ia(i),i=1,5,2)/3*123/
data (ia(i),i=2,4,2)/2*456/
write(*,'(1x,5I4)') (ia(i),i=1,5)
end


eller mere gammeldags:


dimension ia(5)
data (ia(i),i=1,5,2)/3*123/
data (ia(i),i=2,4,2)/2*456/
write(*,'(1x,5I4)') (ia(i),i=1,5)
end



Gravatar #32 - larsp
11. sep. 2023 05:55
arne_v (31) skrev:
#3

Et vigtigt element i Python løsningerne er hvad jeg kalder "den vandrette for løkke". Konstruktionen har sikkert et rigtigt navn i Python.

De hedder "list comprehensions". Jeg har ikke nogen god idé til en dansk oversættelse. Der er også dictionary comprehensions:

d = {k:v for k, v in iterable}


Dine Fortraneksempler er ulæselige for mig. Hvor er løkke-featuren? i=1,5,2? Det er kun tre elementer, eller 1 til 5 step 2. Er det i=1,5 som looper fem gange svarende til ia(5)?
Gravatar #33 - arne_v
11. sep. 2023 10:58
#32

i=1,5,2 er i 1 til 5 step 2
i=1,5 er i 1 til 5
Gravatar #34 - arne_v
11. sep. 2023 13:58
#32

Det ækvivalente Python må være:

ia = [123 if (i % 2 == 0) else 456 for i in range(5)]
print([ia[i] for i in range(5)])

omend den sidste linie i dette tilfælde kan laves simplere med:

print(ia)
Gravatar #35 - arne_v
11. sep. 2023 15:07
#32 #33 #34

Fortran implied do loop er klart mere primitiv og ikke så fleksibel som Python list comprehension.

Men respekt for alder.

Jeg lavede lidt research.

Implied do loop er vist på side 24 i http://bitsavers.informatik.uni-stuttgart.de/pdf/i... og det dokument er dateret 15. oktober 1956.

Python fik list comprehension i version 2.0 44 år senere.

Man bliver lidt klogere på 44 år. :-)

Gravatar #36 - Claus Jørgensen
12. sep. 2023 11:21
#33

heh, 1-based arrays. Det minder mig om da min mor var i Stockholm den anden uge og på undergrundsbanen så hun at der hang en programmerings gåde (fra et konsulentfirma der hyrer folk) med noget array/string manipulation (for at lave en URL man kan besøge)

Hun var meget forvirret indtil jeg forklarede at array indexing er 0-based i Python (og de fleste andre sprog) :p

I PL/I starter arrays nemlig også med 1

Gravatar #37 - arne_v
12. sep. 2023 12:48
#36

Cobol arrays starter også med 1.

Som hoved regel:

meget gamle sprog : starter med 1
begin end sprog : bruger bestemt
curly bracket sprog og nyere sprog : starter med 0
Gravatar #38 - arne_v
12. sep. 2023 19:38
#37

Pascal:


program arix(input,output);

type
r4 = -2..7;
e5 = (a,b,c,d,e,f,g,h,i,j);

var
a1 : array [1..10] of integer;
a2 : array [0..9] of integer;
a3 : array [-5..4] of integer;
a4 : array [r4] of integer;
a5 : array [e5] of integer;
ix1, ix2, ix3 : integer;
ix4 : r4;
ix5 : e5;

begin
for ix1 := lower(a1) to upper(a1) do begin
a1[ix1] := ix1 * ix1;
writeln(ix1, ' ', a1[ix1]);
end;
for ix2 := lower(a2) to upper(a2) do begin
a2[ix2] := ix2 * ix2;
writeln(ix2, ' ', a2[ix2]);
end;
for ix3 := lower(a3) to upper(a3) do begin
a3[ix3] := ix3 * ix3;
writeln(ix3, ' ', a3[ix3]);
end;
for ix4 := lower(a4) to upper(a4) do begin
a4[ix4] := ix4 * ix4;
writeln(ix4, ' ', a4[ix4]);
end;
for ix5 := lower(a5) to upper(a5) do begin
a5[ix5] := ord(ix5) * ord(ix5);
writeln(ix5, ' ', a5[ix5]);
end;
end.
Gravatar #39 - larsp
13. sep. 2023 07:13
#38

Pascal har godt nok mange features hvad angår arrays og deres indexes. Det er pudsigt at de nuværende populære sprog har valgt at droppe den slags fuldstændig. Vil man have funky indexes må man gribe fat i et dictionary eller map.

e5 er vel en art enum?

"array [0..9] of integer" gør ondt i mine øjne, da jeg antager at 9 er inklusiv, så der er 10 elementer. Det er så normalt i de moderne sprog at slutangivelsen er eksklusiv, f.eks. Python:

>>> a = "123456789abcdefg"
>>> a[0:9]
'123456789'
Gravatar #40 - larsp
13. sep. 2023 08:57
... det minder mig iøvrigt om intervaller som undervist i gymnasiematematik:

[0, 9] er 0 til og med 9

[0, 9[ er 0 til 9, men uden 9

Med det in mente har Pascal jo fat i den lange ende og python er forvirrende ;)

Gravatar #41 - Claus Jørgensen
13. sep. 2023 09:17
#40

Matematikere elsker forvirrende konstruktioner (og græske bogstaver som variabler, i stedet for faktisk navne -- hvilket er hvorfor de er så dårlige til at programmere)

Jeg synes personligt dette her er nemmere at forstå (Swift ranges):

0...9
0..<9

https://developer.apple.com/documentation/swift/ra...
Gravatar #42 - arne_v
13. sep. 2023 12:27
larsp (39) skrev:

Pascal har godt nok mange features hvad angår arrays og deres indexes. Det er pudsigt at de nuværende populære sprog har valgt at droppe den slags fuldstændig. Vil man have funky indexes må man gribe fat i et dictionary eller map.


Der er en historisk kontekst.

Wirth designede Pascal til brug for undervisning. De studerende skulle lære pæn programmering. Bruger bestemte array index kan undgå nogle "grimme" beregninger af array index.

Ritchie designed C for Unix. Det skulle ikke være pænt - det skulle være effektivt. Så altid 0 baseret index gav mening. Det sparer nogle maskin instruktioner. Og han havde også langt mindre plads at boltre sig på end Wirth.

Den første Pascal blev implementeret på en CDC Cyber 170 som har 18 bit addresser af 60 bit ord = 262144 ord @ 60 bit = 2621440 bytes @ 6 bit. Den første C og Unix blev implementeret på en DEC PDP-11 som har 16 bit adresser af 8 bit bytes = 65536 bytes @ 8 bit.

Da Stroustrup designede C++ var det et bevidst valg at det skulle være C kompatibelt. Så altid 0 baseret. De første C++ compilere (cfront) var ikke engang compilere men transpilere efter moderne terminologi da de oversatte C++ til C.

Da Gosling designede Java var det overordnede mål et sprog som var mere sikker og simplere end C++ (at Java er blevet kompleks med årene er en anden sag - det vidste han ikke dengang i midt 90erne). Hvis det skulle være simplere end C++ så var det ikke sagen med flere muligheder for array index. Så altid 0 baseret.

Da Hejlsberg designed C# var det overordnede mål et sprog som var en forbedret Java. Så altid 0 baseret. Også selvom han jo oprindeligt kommer fra Pascal verdenen.

Language designer anno 2023: det er da ikke muligt at have andet end 0 baserede array index??

larsp (39) skrev:

e5 er vel en art enum?


Ja. Pascal syntax for enum.

Gravatar #43 - arne_v
13. sep. 2023 13:21
larsp (39) skrev:

Det er så normalt i de moderne sprog at slutangivelsen er eksklusiv, f.eks. Python:

>>> a = "123456789abcdefg"
>>> a[0:9]
'123456789'


Der er jo 3 varianter af dette:

str.substr(startincl, endincl)
str.substr(startincl, endexcl)
str.substr(startincl, length)

Jeg kan faktisk bedst lide den tredie!

:-)

Gravatar #44 - arne_v
13. sep. 2023 13:54
arne_v (43) skrev:

Der er jo 3 varianter af dette:

str.substr(startincl, endincl)
str.substr(startincl, endexcl)
str.substr(startincl, length)


The votes are in.

str.substr(startincl, endincl)

Fortran


program strix
character*5 s
s = 'ABCDE'
write(*,*) s(1:3)
write(*,*) s(2:4)
write(*,*) s(3:5)
end


str.substr(startincl, endexcl)

Python:


s = 'ABCDE'
print(s[0:3])
print(s[1:4])
print(s[2:5])


Java:


public class Strix {
public static void main(String[] args) {
String s = "ABCDE";
System.out.println(s.substring(0, 3));
System.out.println(s.substring(1, 4));
System.out.println(s.substring(2, 5));
}
}


str.substr(startincl, length)

Cobol:


IDENTIFICATION DIVISION.
PROGRAM-ID.STRIX.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 S PIC X(5) VALUE "ABCDE".
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
DISPLAY S(1:3)
DISPLAY S(2:3)
DISPLAY S(3:3)
STOP RUN.



Pascal (Delphi/FPC):


program strix(input, output);

var
s : string;

begin
s := 'ABCDE';
writeln(copy(s, 1, 3));
writeln(copy(s, 2, 3));
writeln(copy(s, 3, 3));
end.



C++:


#include <iostream>
#include <string>

using namespace std;

int main()
{
string s = "ABCDE";
cout << s.substr(0, 3) << endl;
cout << s.substr(1, 3) << endl;
cout << s.substr(2, 3) << endl;
return 0;
}



C#:


using System;

public class Strix
{
public static void Main(string[] args)
{
string s = "ABCDE";
Console.WriteLine(s.Substring(0, 3));
Console.WriteLine(s.Substring(1, 3));
Console.WriteLine(s.Substring(2, 3));
}
}


Gravatar #45 - larsp
13. sep. 2023 14:25
arne_v (43) skrev:
Der er jo 3 varianter af dette:

str.substr(startincl, endincl)
str.substr(startincl, endexcl)
str.substr(startincl, length)

Jeg kan faktisk bedst lide den tredie!

Python slices har nu nogle frække muligheder der er logiske i det der bruges anden variant. Blank betyder første eller sidste element, negativ betyder trukket fra enden:


>>> a = "ABCDE"
>>> a[:-1], a[-1:]
('ABCD', 'E')


Gravatar #46 - larsp
13. sep. 2023 14:29
Claus Jørgensen (41) skrev:
Jeg synes personligt dette her er nemmere at forstå (Swift ranges):

0...9
0..<9

https://developer.apple.com/documentation/swift/ra...

Det er faktisk en helt pæn syntaks.

Har Swift tilsvarende shortcuts som Python, vist i #45?
Gravatar #47 - arne_v
13. sep. 2023 14:42
larsp (45) skrev:
arne_v (43) skrev:
Der er jo 3 varianter af dette:

str.substr(startincl, endincl)
str.substr(startincl, endexcl)
str.substr(startincl, length)

Jeg kan faktisk bedst lide den tredie!

Python slices har nu nogle frække muligheder der er logiske i det der bruges anden variant. Blank betyder første eller sidste element, negativ betyder trukket fra enden:


>>> a = "ABCDE"
>>> a[:-1], a[-1:]
('ABCD', 'E')



At man kan undlade at angive længden og at det betyder resten kendes også fra andre sprog.

At bruge negativ for at tælle RtoL i.s.f. LtoR kan jeg ikke umiddelbart komme i tanke om andre sprog som gør.

Python kode er meget udtryksfuldt.
Gravatar #48 - arne_v
13. sep. 2023 15:19
#41

Ja. Det er faktisk en fornuftig eksplicit syntaks.

Jeg kan ikke lide at de starter med et eksempel med floating point - givet at ikke alle text decimale udstryk kan repræsenteres eksakt i binær floating point er inkl. og ekskl. upper bound lidt uldent for floationg point.

(jeg antager at 0.0 og 5.0 er floating point konstanter og ikke decimal konstanter i Swift)
Gravatar #49 - arne_v
13. sep. 2023 15:20
#41

Kan metoden bruges på lower bound også?

1...5
1..<5

kender vi, men hvad med:

1<..5

?
Gravatar #50 - Claus Jørgensen
13. sep. 2023 23:49
#49

Nej, kun upper bound
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login