2017-12-31 16 views
0

Ich bin ein Algebra-Rechner zu bauen und ich arbeite an einer rekursiven Funktion zum Filtern von Begriffen aus einem Polynom. Die folgende Funktion arbeitet so, dass sie das gewünschte Array von Arrays mit ähnlichen Termen erzeugt. Ich kann dies überprüfen, indem ich der Funktion eine console.log-Anweisung hinzufüge. Aus irgendeinem Grund gibt die Funktion die Ausgabe jedoch nicht zurück. Es gibt "undefined" zurück.Rekursive Javascript-Funktion mit Argumenten Eigenschaft gibt die richtige Antwort, aber gibt undefined zurück

Mein Denken ist, dass die Kette der rekursiven Aufrufe mit der unten angegebenen Endbedingung enden sollte, und übergeben Sie dann das zurückgegebene Argument [1] -Array durch den Stapel.

Ich habe ähnliche Fragen hier gelesen, wo die Person vergisst, eine Return-Anweisung an einem oder mehreren Orten zu setzen. In meinem Code habe ich jedoch eine return-Anweisung mit der Endbedingung und mit dem rekursiven Funktionsaufruf. Es ist wahrscheinlich etwas einfaches, das ich vermisse.

var filterLikeTerms = function (terms) { //takes an array of terms, optional second argument is an array of arrays of similar terms 
 
    if (!arguments[1]) arguments[1] = []; //Initilizes the second argument if none is given 
 
    if (terms.length == 0) return arguments[1]; //End condition 
 
    arguments[1].push(terms.filter(term => terms[0].toString() === term.toString())); //Adds similar terms to the 2nd argument array 
 
    terms = terms.filter (term => terms[0].toString() !== term.toString()); //shortens the terms array to exclude the like terms filtered above 
 
    return filterLikeTerms(terms, arguments[1]); //recursive function call 
 
}

+0

Post, was Sie rufen 'filterLikeTerms' mit auf? Sie rufen '.toString' für eine Eigenschaft auf, die als Zeichenfolge übergeben werden muss. Sie können nicht "7x + 1" als Wert übergeben. Es wäre schon eine Zeichenfolge. Zweite Anmerkung, es scheint, als ob der Code versucht, schlau zu sein. Machen Sie einen Schritt zurück, machen Sie es einfach, durchzulaufen und optimieren Sie später. – VtoCorleone

+0

Vielleicht verstehe ich die Frage nicht, aber wenn ich 'console.log (filterLikeTerms (['A', 'B', 'C', 'D']))', druckt Array von Arrays und nicht undefiniert .. – bigless

+0

Sie können Parameter 'arguments' nicht an die Methode übergeben, da sie nur einen Parameter akzeptieren:' terms'. Ich denke, Sie müssen die Methode machen, um 2 Parameter 'filterLikeTerms (Begriffe, Argumente) 'zu akzeptieren. Ein Beispiel für den Prozess kann Ihre Fragen verständlicher machen, wie die Beispieleingaben und die erwarteten Ausgaben. – Eaton

Antwort

0

Arbeit intelligent, nicht härter

Versuchen Sie nicht dem Kopf mit unnötigen Variablen, Zuweisungen oder logischen Bedingungen zu verletzen - eine einfache rekursive Funktion mit einfacher Gleichheit Prüfung

const eq = x => y => 
 
    x === y 
 

 
const neq = x => y => 
 
    x !== y 
 

 
const filterLikeTerms = ([ x, ...xs ]) => 
 
    x === undefined 
 
    ? [] 
 
    : [ xs.filter (eq (x)) ] 
 
     .concat (filterLikeTerms (xs.filter (neq (x)))) 
 

 
const data = 
 
    ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'a', 'b'] 
 

 
console.log (filterLikeTerms (data)) 
 
// [ [ a, a, a ] 
 
// , [ b, b ] 
 
// , [ c ] 
 
// , [ d ] 
 
// ]

Flexible Implementierung

Wenn Sie ändern möchten, wie Elemente werden miteinander verglichen und gruppiert, geändert eq und neq

// for example ... 
const eq = x => y => 
    x.toString() === y.toString() 

const neq = x => y => 
    x.toString() !== y.toString() 

Wenn Sie den Speicher-Parameter verwenden möchten, wie Sie haben in Ihrem Original-Code, das ist auch in Ordnung - diese Form kann einfach gemacht werden stack-safe für sehr große Eingänge

const filterLikeTerms = ([ x, ...xs ], acc = []) => 
    x === undefined 
    ? acc 
    : filterLikeTerms (xs.filter (neq (x)) 
         , acc.concat ([ xs.filter (eq (x)) ]) 
        ) 

Arbeit auch smarterer

Die richtige Endrekursion (unmittelbar oben) stellt uns mit riesigen Dateneingaben zu arbeiten, aber unsere Funktion ist sehr ineffizient, da mehrere Filter läuft für jedes Element in der Liste. Wir können eine dramatische Verbesserung machen durch die Verwendung eines Map - jetzt nur wir jedes Element in der ursprünglichen Eingangs berühren einmal

const filterLikeTerms = ([ x, ...xs ], acc = new Map) => 
 
    x === undefined 
 
    ? Array.from (acc.values()) 
 
    : acc.has (x) 
 
     ? filterLikeTerms (xs, acc.set (x, [x].concat (acc.get (x)))) 
 
     : filterLikeTerms (xs, acc.set (x, [x])) 
 

 
const data = 
 
    ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'a', 'b'] 
 

 
console.log (filterLikeTerms (data))


Sie nicht aufhören zu lernen, noch

Sie können alle Arten von schönen Dingen auf eigene Faust machen.Hier einige Dinge, die ich schrieb, die auf diese Antwort beziehen:

0

In ES6:

const filterLikeTerms=terms=>[...(new Set(terms))] 
Verwandte Themen