Javascript "switch/case" Problem
akuep
- javascript
0 JürgenB0 akuep0 Tabellenkalk
0 Rolf B0 Matthias Scharwies
Ich habe ein kleines Converter-Programm geschrieben, dass leider nicht ganz funktioniert.
Über ein Selections-Menü (let unit_ID = parseInt(form1.elements.auswahl.value);
)soll die Umrechnungseinheit ausgewählt werden (value=1
bis..).
Wenn "1" gewählt, soll diese Einheit umgerechnet werden.
Wenn "2" gewählt soll die nächste Einheit umgerechnet werden, usw.
Ich habe dies versucht über "switch" und "case" .
Der erste "case" funktioniert, die weiteren nicht mehr.
Ich bin schon seit Tagen damit beschäftigt. Bekomme es einfach nicht hin.
Vielen Dank für Eure Hilfe.
Hier dieses Skript:
<script>
function convert() {
"use strict";
let unit_ID = parseInt(form1.elements.auswahl.value);
let factor1_1 = 1.0;
let factor1_2 = 0.1;
let factor1_3 = 100;
let factor1_4 = 0.987;
let factor1_5 = 0.00004403;
let factor1_6 = 0.002097;
let factor2_1 = 10;
let factor2_2 = 1;
let factor2_3 = 1000;
let factor2_4 = 9.87;
let factor2_5 = 0.0004403;
let factor2_6 = 0.02097;
let factor3_1 = 0.01;
let factor3_2 = 0.001;
let factor3_3 = 1;
let factor3_4 = 0.00987;
let factor3_5 = 0.0000004403;
let factor3_6 = 0.00002097;
let input_wert = parseFloat(form1.elements.inputvalue.value);
switch (unit_ID) {
case (unit_ID===1):
let wert1 = input_wert * factor1_1;
parseFloat(form1.elements.value01.value) = wert1;
let wert2 = input_wert * factor1_2;
parseFloat(form1.elements.value02.value) = wert2;
let wert3 = input_wert * factor1_3;
parseFloat(form1.elements.value03.value) = wert3;
let wert4 = input_wert * factor1_4;
parseFloat(form1.elements.value04.value) = wert4;
let wert5 = input_wert * factor1_5;
parseFloat(form1.elements.value05.value) = wert5;
let wert6 = input_wert * factor1_6;
parseFloat(form1.elements.value06.value) = wert6;
break;
case (unit_ID===2):
let wert1 = input_wert * factor2_1;
parseFloat(form1.elements.value01.value) = wert1;
let wert2 = input_wert * factor2_2;
parseFloat(form1.elements.value02.value) = wert2;
let wert3 = input_wert * factor2_3;
parseFloat(form1.elements.value03.value) = wert3;
let wert4 = input_wert * factor2_4;
parseFloat(form1.elements.value04.value) = wert4;
let wert5 = input_wert * factor2_5;
parseFloat(form1.elements.value05.value) = wert5;
let wert6 = input_wert * factor2_6;
parseFloat(form1.elements.value06.value) = wert6;
break;
}
}
</script>
Hallo,
kennst du schon https://wiki.selfhtml.org/wiki/JavaScript/Verzweigung#Fallunterscheidung_mit_.22switch.22?
Gruß
Jürgen
Danke. Ja, den kannte ich. Und habe mich auch daran orientiert.
Der erste Fall in meinem Script funktioniert, die weiteren nicht mehr.
Hallo,
im Wiki werden zwei Fälle behandelt:
switch (Eingabe) {
case "1":
Text = 'Sie sind sehr bescheiden!';
break;
case "2":
Text = 'Sie sind ein aufrichtiger Zweibeiner!';
break;
…
und
switch (true) {
case EingabeWert < 50:
Text = 'Die Zahl ' + Eingabe + ' ist sicher zu klein.';
break;
case EingabeWert > 100:
Text = 'Die Zahl ' + Eingabe + ' ist eindeutig zu groß.';
break;
default:
Text = 'Na bitte, Sie haben die Aufgabe verstanden!';
break;
}
Deine Variante kenne ich nicht.
Gruß
Jürgen
Hallo JürgenB,
seine Variante ist ein Mix aus Variante 1 und 2, die nicht funktionieren kann. Entweder switch(true)
und in den Case-Labels eine Bedingung, oder switch(wert)
und in den Case-Labels die Vergleichswerte.
Für die unit_ID 1 kommt in seinem Code zur Laufzeit heraus:
switch (1) {
case true: ...
case false: ...
case false: ...
}
und das trifft niemals zu, weil switch den Switch-Wert auf Identität mit dem Case-Label vergleicht und nicht auf Wertgleichheit (also 1 === true statt 1 == true). Es sei denn, da verhalten sich die JS-Engines unterschiedlich. In Chrome funktioniert es jedenfalls nicht.
Und wenn das gefixt ist, fliegt er mit der Zuweisung an parseFloat() auf die Nase. Das crasht derzeit nur deshalb nicht, weil keins der case-Labels zutrifft.
Insofern: "Der erste Fall in meinem Script funktioniert, die weiteren nicht mehr." würde ich gerne live und in Farbe sehen. Andernfalls halte ich das für erfunden, denn es sind 2 Fehler im Code, die das verhindern.
Rolf
Hallo Rolf,
wenn keiner der Fälle zutrifft und es auch kein default: gibt, wird der erste genommen.
Gruß
Jürgen
Hi,
wenn keiner der Fälle zutrifft und es auch kein default: gibt, wird der erste genommen.
ab wann?
Bisher wird dann keiner der cases genutzt.
cu,
Andreas a/k/a MudGuard
Hallo Andreas,
Bisher wird dann keiner der cases genutzt.
stimmt. Da habe ich die Doku nicht richtig gelesen.
Gruß
Jürgen
Hallo,
kennst du schon https://wiki.selfhtml.org/wiki/JavaScript/Verzweigung#Fallunterscheidung_mit_.22switch.22?
jetzt ja!
Ich hab ein Dreirad gewonnen! Wo kann ich das abholen?
Gruß
Kalk
Servus!
Hallo,
kennst du schon https://wiki.selfhtml.org/wiki/JavaScript/Verzweigung#Fallunterscheidung_mit_.22switch.22?
jetzt ja!
Ich hab ein Dreirad gewonnen! Wo kann ich das abholen?
JH Mannheim, ca. 5min vom Mannheimer Hbf gelegen,
Herzliche Grüße
Matthias Scharwies
Hallo akuep,
ich denke, der von Jürgen verlinkte Wiki-Artikel sollte Dir helfen, dein Entscheidungsproblem zu lösen.
Allerdings...
Der erste "case" funktioniert, die weiteren nicht mehr.
Erzähle bitte keine Märchen. Der erste Case funktioniert auch nicht.
parseFloat(form1.elements.value01.value) = wert1;
ist ein Fehler (in der Browserkonsole siehst Du die Meldung, dass ein ReferenceError nicht "gefangen" worden sei). Ich denke, du hast einfach blindlings das Auslesen der Werte aus den input-Elementen irgendwoher kopiert, ohne es zu verstehen.
form1.elements.value01
name="value01"
im Form form1
.form1.elements.value01.value
value
-Eigenschaft dieses Elements, in Form einer Zeichenkette. Dieser Eigenschaft kann man auch etwas zuweisen.parseFloat(...)
parseFloat
. Sie wandelt eine Zeichenkette nach bestem Können in eine Zahl um. An das Ergebnis eines Funktionsaufrufs kann man aber nichts zuweisen.Was funktioniert, ist:
form1.elements.value01.value = input_value * faktor;
Jedenfalls so halbwegs. Hier müsste eigentlich eine brauchbare Rundung erfolgen. Was "brauchbar" ist, hängt auch von den Umrechnungsfaktoren ab. Wenn ich mit 0.00004403 multipliziere, sind vermutlich 8 Nachkommastellen signifikant. Natürlich ist die Frage, ob es sinnvoll ist, Millimeter in Meilen umzurechnen oder sowas… Einfaches Runden geht mit toFixed:
form1.elements.value01.value = (input_value * faktor).toFixed(8);
rundet auf 8 Nachkommastellen, bzw. füllt mit Nullen auf 8 Stellen auf.
Im Übrigen würde ich Dir empfehlen, auf den case zu verzichten und ein Array mit Umrechnungsfaktoren zu verwenden. Was ich Dir aber, damit Du es verstehst, 1:1 vorkauen müsste und damit dein Abschreibebegehren erfüllen würde. Nö. Tu ich nicht.
Rolf
Hallo Rolf,
vielen Dank.
Es kommt mir nicht auf einen optimierten Code an. Ich muss ihn einfach halten, damit ich ihn nach Jahren noch nachvollziehen kann.
ich habe ihn im Prinzip beibehalten, jedoch ein Paar Änderungen durchgeführt.
Es läuft jetzt für die ersten 3 Konvertierungen. Es werden noch 3 dazukommen.
Falls noch grundsätzliche Fehler auffallen, wäre es schön, wenn ihr euch noch einmal meldet.
Danke.
Hier mein Script:
function convert() {
"use strict";
let unit_ID = parseInt(form1.elements.auswahl.value);
let factor1_1 = 1.0;
let factor1_2 = 0.1;
let factor1_3 = 100;
let factor1_4 = 0.987;
let factor1_5 = 0.00004403;
let factor1_6 = 0.002097;
let factor2_1 = 10;
let factor2_2 = 1;
let factor2_3 = 1000;
let factor2_4 = 9.87;
let factor2_5 = 0.0004403;
let factor2_6 = 0.02097;
let factor3_1 = 0.01;
let factor3_2 = 0.001;
let factor3_3 = 1;
let factor3_4 = 0.00987;
let factor3_5 = 0.0000004403;
let factor3_6 = 0.00002097;
let input_wert = parseFloat(form1.elements.inputvalue.value);
switch (unit_ID) {
case (unit_ID=1):
let wert1 = (input_wert * factor1_1).toFixed(4);
form1.elements.value01.value = wert1;
let wert2 = (input_wert * factor1_2).toFixed(4);
form1.elements.value02.value = wert2;
let wert3 = (input_wert * factor1_3).toFixed(4);
form1.elements.value03.value = wert3;
let wert4 = (input_wert * factor1_4).toFixed(4);
form1.elements.value04.value = wert4;
let wert5 = (input_wert * factor1_5).toFixed(4);
form1.elements.value05.value = wert5;
let wert6 = (input_wert * factor1_6).toFixed(4);
form1.elements.value06.value = wert6;
break;
case (unit_ID=2):
let wert7 = (input_wert * factor2_1).toFixed(4);
form1.elements.value01.value = wert7;
let wert8 = (input_wert * factor2_2).toFixed(4);
form1.elements.value02.value = wert8;
let wert9 = (input_wert * factor2_3).toFixed(4);
form1.elements.value03.value = wert9;
let wert10 = (input_wert * factor2_4).toFixed(4);
form1.elements.value04.value = wert10;
let wert11 = (input_wert * factor2_5).toFixed(4);
form1.elements.value05.value = wert11;
let wert12 = (input_wert * factor2_6).toFixed(4);
form1.elements.value06.value = wert12;
break;
case (unit_ID=3):
let wert13 = (input_wert * factor3_1).toFixed(4);
form1.elements.value01.value = wert13;
let wert14 = (input_wert * factor3_2).toFixed(4);
form1.elements.value02.value = wert14;
let wert15 = (input_wert * factor3_3).toFixed(4);
form1.elements.value03.value = wert15;
let wert16 = (input_wert * factor3_4).toFixed(4);
form1.elements.value04.value = wert16;
let wert17 = (input_wert * factor3_5).toFixed(4);
form1.elements.value05.value = wert17;
let wert18 = (input_wert * factor3_6).toFixed(4);
form1.elements.value06.value = wert18;
break;
}
}
Servus!
Hallo Rolf,
vielen Dank.
Es kommt mir nicht auf einen optimierten Code an. Ich muss ihn einfach halten, damit ich ihn nach Jahren noch nachvollziehen kann.
Doch, wenn er auf den Anwendungsfall optimiert wäre, könnte man ihn noch nach Jahren nachvollziehen.
Du verwendest viele ähnliche Magic Numbers, aber keine Formeln, die das irgendwie in Beziehung setzen.
Herzliche Grüße
Matthias Scharwies
@@akuep
Hier mein Script:
Jetzt habe ich schon zum zweiten Mal ein Posting von dir lesbar gemacht. Beim dritten Mal machst du es bitte selbst. Siehe Abschnitt „Code“ in der Hilfe, insb. die Unterscheidung zwischen Inline-Code und Codeblöcken.
Beides lässt sich auch mit dem </>
-Button überm Eingabefeld machen. Für dich getestet:
Inline: void()
{
void();
}
Kwakoni Yiquan
Ohne den genauen Anwendungsfall zu kennen (weil du ihn – warum auch immer – nicht beschreiben möchtest), erscheint mir das switch
-Statement hier der falsche Ansatz zu sein.
Du hast drei Units mit jeweils sechs Faktoren, die sich offensichtlich nicht ändern. Anstatt 19 (!) Variablen darauf zu verschwenden, ließe sich die Struktur als Objekt darstellen.
In deinem switch
-Statement werden (unabhängig von der gewählten Unit) sechs Ausgabefelder mit neuen Werten befüllt. Der neue Wert wird in jedem Fall nach der selben Formel berechnet.
Mir scheint, als könne das ganze über einen einfachen for
-Loop laufen. Kommen neue Units dazu oder ändern sich die Faktoren, muss im Script lediglich das Faktor-Objekt angepasst werden.
Ungetestetes Beispiel anbei. Das geht mit Sicherheit besser/eleganter/robuster/was-auch-immer. Ohne den genauen Anwendungsfall zu kennen, möchte ich da aber nicht mehr als ein paar Minuten investieren.
<!DOCTYPE html><html lang=de><meta charset=UTF-8><meta name=viewport content="width=device-width, initial-scale=1">
<title>Seltsamer Konverter</title>
<script type=module>
const factors = {
'unit_1': {
1: 1.0,
2: 0.1,
3: 100,
4: 0.987,
5: 0.00004403,
6: 0.002097
},
'unit_2': {
1: 10,
2: 1,
3: 1000,
4: 9.87,
5: 0.0004403,
6: 0.02097
},
'unit_3': {
1: 0.01,
2: 0.001,
3: 1,
4: 0.00987,
5: 0.0000004403,
6: 0.00002097
}
};
document.forms.convert.addEventListener('submit', function (event) {
const
valueSeed = event.currentTarget.elements.seed.value,
valueUnit = event.currentTarget.elements.unit.value;
for (let i = 1; i <= 6; i++) {
event.currentTarget.elements[`out-${i}`].value = valueSeed * factors[`unit_${valueUnit}`][i].toFixed(4);
}
event.preventDefault();
});
</script>
<form id=convert>
<div>
<label for=seed>Startwert</label>
<input id=seed type=number required>
</div>
<fieldset>
<legend>Unit</legend>
<div>
<input type=radio name=unit id=unit-1 value=1 required checked>
<label for=unit-1>Unit 1</label>
</div>
<div>
<input type=radio name=unit id=unit-2 value=2 required>
<label for=unit-2>Unit 2</label>
</div>
<div>
<input type=radio name=unit id=unit-3 value=3 required>
<label for=unit-3>Unit 3</label>
</div>
</fieldset>
<fieldset>
<legend>Ausgabe</legend>
<div>
<label for=out-1>Wert 1:</label>
<output id=out-1>0</output>
</div>
<div>
<label for=out-2>Wert 2:</label>
<output id=out-2>0</output>
</div>
<div>
<label for=out-3>Wert 3:</label>
<output id=out-3>0</output>
</div>
<div>
<label for=out-4>Wert 4:</label>
<output id=out-4>0</output>
</div>
<div>
<label for=out-5>Wert 5:</label>
<output id=out-5>0</output>
</div>
<div>
<label for=out-6>Wert 6:</label>
<output id=out-6>0</output>
</div>
</fieldset>
<button>konvertiere</button>
</form>
Hallo Loopie McLoop,
kann man so machen, ja. Ich persönlich hätte großzügig Anführungszeichen um die Attributwerte verteilt, aber das ist Formalkram.
Prinzipiell hatte ich das ja auch schon angeregt, aber diesen Kommentar dazu gesetzt:
Was ich Dir aber, damit Du es verstehst, 1:1 vorkauen müsste und damit dein Abschreibebegehren erfüllen würde. Nö. Tu ich nicht.
Lass mich kurz über deinen Vorschlag philosophieren…
Du hast für das Faktorenverzeichnis Objekte geschachtelt. Das dürfte eine bessere Ide sein als mein Array-Ansatz – ich würde dann aber konsequent sein und sowohl für die Unit-Auswahl wie auch für die Faktoren die entsprechenden Keys direkt verwenden und nicht zusammensetzen. Im abstrakten Beispiel ist unit-1 und out-4 okay, für einen realen Anwendungsfall könnte dann aber auch "metrisch" und "kilometer" angebracht sein.
Also (verkürzt auf die input-Elemente):
<script>
const factors = {
'unit-1': {
'out-1': 1.0,
'out-2': 0.1,
'out-3': 100,
'out-4': 0.987,
'out-5': 0.00004403,
'out-6': 0.002097
},
...
};
...
</script>
...
<input type="radio" name="unit" id="unit-1" value="unit-1" required checked>
<input type="radio" name="unit" id="unit-2" value="unit-2" required>
<input type="radio" name="unit" id="unit-3" value="unit-3" required>
Damit kann man direkt auf das richtige Faktorenobjekt zugreifen:
const factorSet = factors[document.convert.unit];
Ob document.convert
oder event.currentTarget
besser ist, ist wohl Geschmackssache. Die currentTarget-Variante ist flexibler, wenn man mehrere dieser Forms auf einer Seite hat, setzt aber auch voraus, dass man das im Submit-Event tut. Ich würde die Konvertierung vielleicht lieber im change-Event des Unit-Fieldset auslösen bzw. im input-Event des Wert-Eingabefeldes, damit die Umrechnung "live" erfolgt.
Rolf
@@Loopie McLoop
Du hast drei Units mit jeweils sechs Faktoren, die sich offensichtlich nicht ändern. Anstatt 19 (!) Variablen darauf zu verschwenden, ließe sich die Struktur als Objekt darstellen.
Ja – wenn man denn die Werte alle brauchen würde.
Die Hälfte braucht man nicht, da der Faktor zur Umrechnung von Einheit A in Einheit B gleich dem Kehrwert des Faktors zur Umrechnung von Einheit B in Einheit A ist.
Man braucht aber noch weniger. Man braucht nur die Faktoren zur Umrechnung in die Grundeinheit, also 5 Werte.
Um bspw. Seemeilen in Zoll umzurechnen, braucht man nicht den Umrechnungsfaktor Seemeilen in Zoll oder andersrum. Man braucht nur Faktoren zur Umrechnung in die Grundeinheit Meter:
1 sm = 1852 m
1ʺ = 0.0254 m
Damit rechnet man:
1 sm = 1852/0.0254 × 1ʺ ≈ 72910ʺ
Kwakoni Yiquan
Servus!
Ich habe ein kleines Converter-Programm geschrieben, dass leider nicht ganz funktioniert.
<script> function convert() { let factor1_4 = 0.987; let factor2_4 = 9.87; let factor3_4 = 0.00987; let factor1_5 = 0.00004403; let factor2_5 = 0.0004403; let factor3_5 = 0.0000004403; } </script>
Die Variablen scheinen mir so ähnlich, dass deine gewählte Vorgehensweise mit Sicherheit auch vereinfacht werden kann.
Könntest du uns sagen, was du erreichen willst? Evtl. kann man dann eine andere Vorgehensweise wählen und diese weiter durchplanen.
Herzliche Grüße
Matthias Scharwies