Tip om kodning: Prøv at kode uden udsagn

Du kan muligvis afsløre bedre løsninger

Kode fra et Facebook-projekt. Venligst ikke sagsøge dem.
Opdatering: Denne artikel er nu en del af min bog "Lær kodning med moderne JavaScript".
Læs den opdaterede version af den på jscomplete.com/no-ifs.

Når jeg lærer begyndere at programmere og præsentere dem for kodeudfordringer, er en af ​​mine yndlingsopfølgende udfordringer: Løs nu det samme problem uden at bruge if-udsagn (eller ternære operatører eller skifte udsagn).

Du spørger måske, hvorfor ville det være nyttigt?

Jeg tror, ​​at denne udfordring tvinger din hjerne til at tænke anderledes, og i nogle tilfælde kan den anden løsning være bedre.

Der er ikke noget galt i at bruge if-udsagn, men at undgå dem kan undertiden gøre koden lidt mere læselig for mennesker. Dette er bestemt ikke en generel regel, da undertiden undgåelse af if-udsagn vil gøre koden meget mindre læselig. Du er dommeren.

At undgå if-udsagn handler ikke kun om læsbarhed. Der er noget videnskab bag konceptet. Som udfordringerne nedenfor viser, når du ikke bruger if-udsagn, kommer du tættere på kode-som-datakonceptet, som åbner døren for unikke muligheder som at ændre koden, mens den udføres!

I alle tilfælde er det altid sjovt at prøve at løse en kodningsudfordring uden brug af konditioneringsmaterialer.

Her er nogle eksempler på udfordringer med deres if-baserede løsninger og hvis-mindre løsninger. Alle løsninger er skrevet i JavaScript.

Fortæl mig, hvilke løsninger synes du er mere læsbare.

Udfordring # 1: Tæl de ulige heltal i en matrix

Lad os sige, at vi har en række heltal, og vi vil tælle, hvor mange af disse heltal er underlige.

Her er et eksempel til test med:

const arrayOfIntegers = [1, 4, 5, 9, 0, -1, 5];

Her er en løsning ved hjælp af en if-statement:

lad tæller = 0;
arrayOfIntegers.forEach ((heltal) => {
  const rest = Math.abs (heltal% 2);
  if (resten === 1) {
    counter ++;
  }
});
console.log (tæller);

Her er en løsning uden if-udsagn:

lad tæller = 0;
arrayOfIntegers.forEach ((heltal) => {
  const rest = Math.abs (heltal% 2);
  tæller + = resten;
});
console.log (tæller);

Bemærk: ovenstående eksempler bruges for Hvert og muter tællervariablen. Det er renere og sikrere at bruge uforanderlige metoder i stedet. Denne artikel handler imidlertid ikke om dette emne. Hold øje med flere artikler om kodningstip, der dækker uforanderlighed og funktionel programmering. Bemærk også, som David Nagli påpegede, at den hvis mindre løsning kun ville fungere for heltal, mens den if-baserede løsning har fordelen ved at håndtere ethvert antal inklusive decimaler.

I den mindre løsning drager vi fordel af det faktum, at resultatet af drift af modul 2 altid er enten 1 (for ulige) eller 0 (for lige). Dette resultat er data. Vi brugte lige disse data direkte.

Hvad med at tælle selv heltal? Kan du tænke på en måde at gøre det på uden at bruge en if-statement?

Udfordring # 2: Funktionen weekendOrWeekday

Skriv en funktion, der tager et datoobjektargument (som ny dato ()) og returnerer strengen "weekend" eller "ugedag".

Her er en løsning ved hjælp af en if-statement:

const weekendOrWeekday = (inputDate) => {
  const day = inputDate.getDay ();
  if (dag === 0 || dag === 6) {
    vende tilbage 'weekend';
  }
  
  returnere 'ugedag';
  // Eller for ternære fans:
  // retur (dag === 0 || dag === 6)? 'weekend': 'weekday';
};
console.log (weekendOrWeekday (ny dato ()));

Her er en løsning uden if-udsagn:

const weekendOrWeekday = (inputDate) => {
  const day = inputDate.getDay ();
  retur weekendOrWeekday.labels [day] ||
         weekendOrWeekday.labels [ 'standard'];
};
weekendOrWeekday.labels = {
  0: 'weekend',
  6: 'weekend',
  standard: 'ugedag'
};
console.log (weekendOrWeekday (ny dato ()));

Bemærkede du, at tilstanden if-statement har nogle data i sig? Det fortæller os, hvilke dage der er weekender. Hvad vi gjorde for at undgå if-statement er at udtrække disse data til et objekt og bruge objektet direkte. Det gør os også i stand til at gemme disse data på højere generiske niveauer.

Opdatering: Harald Niesche påpegede korrekt, at || trick ovenfor er teknisk set en betinget ting. Jeg har valgt at bruge det, så jeg ikke gentager "ugedag" fem gange. Vi kan let slippe af med det, hvis vi lægger hele 7 dage i etiketten.

Udfordring # 3: doubler-funktionen (her være drager)

Skriv doublerfunktionen, der, baseret på typen af ​​input, ville gøre følgende:

  • Når input er et tal, dobler det det (dvs. 5 => 10, -10 => -20).
  • Når input er en streng, gentager det hvert bogstav (dvs. 'hello' => 'hheelloo').
  • Når input er en funktion, kalder den den to gange.
  • Når input er en matrix, kalder den sig selv på alle elementer i den array.
  • Når input er et objekt, kalder det sig selv alle objektets værdier.

Her er en løsning ved hjælp af en switch-statement:

const doubler = (input) => {
  switch (typeof input) {
    sagsnummer':
      retur input + input;
    sag 'streng':
      retur input
        .dele('')
        .map ((bogstav) => bogstav + bogstav)
        .tilslutte('');
    sag 'objekt':
      Object.keys (input)
            .kort ((tast) => (input [tast] = doubler (input [tast])));
      retur input;
    sag 'funktion':
      indgang ();
      indgang ();
  }
};
console.log (dobler (-10));
console.log (dobler ( 'hej'));
console.log (doubler ([5, 'hej']));
console.log (doubler ({a: 5, b: 'hej'}));
console.log (
  doubler (funktion () {
    console.log ( 'call-mig');
  }),
);

Her er en løsning uden en switch-statement:

const doubler = (input) => {
  returner doubler.operationsByType [typeof input] (input);
};
doubler.operationsByType = {
  nummer: (input) => input + input,
  streng: (input) =>
    input
      .dele('')
      .map ((bogstav) => bogstav + bogstav)
      .tilslutte(''),
  funktion: (input) => {
    indgang ();
    indgang ();
  },
  objekt: (input) => {
    Object.keys (input)
          .kort ((tast) => (input [tast] = doubler (input [tast])));
    retur input;
  },
};
console.log (dobler (-10));
console.log (dobler ( 'hej'));
console.log (doubler ([5, 'hej']));
console.log (doubler ({a: 5, b: 'hej'}));
console.log (
  doubler (funktion () {
    console.log ( 'call-mig');
  }),
);

Bemærk igen, hvordan dataene (hvilke operationer der skal udføres for hvilken inputtype) alle blev trukket ud af switch-sætningen til et objekt. Derefter blev objektet brugt til at vælge den rigtige handling og påkalde det med det originale input.

Nu hvor du har set et par eksempler, hvad er dine tanker? Har du nogen argumenter for eller imod en af ​​disse to kodningstilarter?

Tak for at have læst.