简体   繁体   English

如何使这个 function 递归/运行直到不满足要求?

[英]How can I make this function recursive/run until the requirements are not met?

As of now, I can only hardcode the same snippet after every if statement, which only needs to have the argument that getAdjacentCells(id) takes changed.到目前为止,我只能在每个 if 语句之后硬编码相同的代码段,只需要更改 getAdjacentCells(id) 需要的参数。 I haven't been able to find a way to repeat this part.我一直无法找到重复这部分的方法。 I think this can be done recursively, but I don't know how to do it.我认为这可以递归完成,但我不知道该怎么做。

Edit: I initially typed that isCellEmpty got an array of objects: [{topLeft: null}, {topCenter: "cell-1-2"}, {topRight: "cell-1-3"}, {middleLeft: null}, {middleRight: "cell-2-3"}], when in reality it is a single object: {topLeft: null, topCenter: "cell-1-2", topRight: "cell-1-3", middleLeft: null, middleRight: "cell-2-3"}编辑:我最初输入 isCellEmpty 有一个对象数组:[{topLeft: null}, {topCenter: "cell-1-2"}, {topRight: "cell-1-3"}, {middleLeft: null}, {middleRight: "cell-2-3"}],实际上它是单个 object:{topLeft: null, topCenter: "cell-1-2", topRight: "cell-1-3", middleLeft: Z307A6278EZBDC8DFF929DFF99 , middleRight: "cell-2-3"}

// Gets an object that looks like this: {topLeft: null, topCenter: "cell-1-2", topRight: "cell-1-3", middleLeft: null, middleRight: "cell-2-3"}
function isCellEmpty(adjacentCells) {
  Object.values(adjacentCells).forEach(id => {
    // Checks that the ids in stored in the object values do not equal null
    if (id !== null) {
      board[getBoardPosition(id)].opened = true;
      // getAdjacentCells() will return either an array of objects similar to the one the function takes as an argument or an integer
      // if getAdjacentCells(id) returns a number, add a div to the HTML element with that id
      if (typeof (getAdjacentCells(id)) === "number") {
        // Removes all other divs, this prevents repetition
        $("#" + id).empty();
        // Appends an empty div
        $("#" + id).append("<div></div>");
      // HERE'S WHERE IT STARTS: If getAdjacentCells(id) returns an object, do the same as above with every id in it
      } else if (typeof (getAdjacentCells(id)) === "object") {
        Object.values(getAdjacentCells(id)).forEach(id2 => {
          if (id2 !== null) {
            board[getBoardPosition(id2)].opened = true;
            if (typeof (getAdjacentCells(id2)) === "number") {
              $("#" + id2).empty();
              $("#" + id2).append("<div></div>");
            // HERE IT REPEATS: 
            } else if (typeof (getAdjacentCells(id2)) === "object") {
              ... 
            }
          }
        })
      }
    }
  });
}

You can make the recursive call with the value you get from getAdjacentCells .您可以使用从getAdjacentCells获得的值进行递归调用。 Make sure however to call getAdjacentCells only once for the same id .但是请确保为相同的id只调用一次getAdjacentCells Now it is quite inefficient as you repeat the same call.现在,当您重复相同的调用时,它的效率非常低。

See also some other suggestions in the code.另请参阅代码中的其他一些建议。

function isCellEmpty(adjacentCells) {
    // I would move this check here, although not necessary if you prefer it in the loop.
    if (typeof adjacentCells === "number") {
        $("#" + id).empty().append("<div>"); // You can chain jQuery...
        return;
    } 
    for (let id of adjacentCells) { // Just use a for..of loop
        if (id === null) continue; // keep IF-ELSE nesting flat.
        let cell = board[getBoardPosition(id)];
        if (cell.opened) continue; // Add this to avoid circling around
        cell.opened = true;
        isCellEmpty(getAdjacentCells(id)); // recursive call
    }
}

Object.values Object.values

You write in the comments of your code that:您在代码的注释中写道:

getAdjacentCells() will return either an array of objects similar to the one the function takes as an argument or an integer getAdjacentCells() 将返回类似于 function 作为参数的对象数组或 integer

However, your comments below this answer seem to suggest that this is not (always) the case.但是,您在此答案下方的评论似乎表明情况并非(总是)如此。 It maybe a plain object which would explain why you used Object.values to iterate it.它可能是一个普通的 object 可以解释为什么你使用Object.values来迭代它。 If this is the case I would urge to change getAdjacentCells so that it really does return an array.如果是这种情况,我会敦促更改getAdjacentCells以便它确实返回一个数组。 Or if that is not possible then use Object.values like you already did:或者,如果这是不可能的,那么就像你已经做过的那样使用Object.values

function isCellEmpty(adjacentCells) {
    // I would move this check here, although not necessary if you prefer it in the loop.
    if (typeof adjacentCells === "number") {
        $("#" + id).empty().append("<div>"); // You can chain jQuery...
        return;
    } 
    for (let id of Object.values(adjacentCells)) { // Just use a for..of loop
        if (id === null) continue; // keep IF-ELSE nesting flat.
        let cell = board[getBoardPosition(id)];
        if (cell.opened) continue; // Add this to avoid circling around
        cell.opened = true;
        isCellEmpty(getAdjacentCells(id)); // recursive call
    }
}

Recursion should work just fine here: at its most basic you'd call your own method with id2 .递归在这里应该可以正常工作:在最基本的情况下,您可以使用id2调用您自己的方法。 However, assuming getAdjacentCells may return cells that you've already visited, you'll end up recursing infinitely unless you're able to track which IDs you've already visited, and pass that in.但是,假设getAdjacentCells可能会返回您已经访问过的单元格,那么您最终会无限递归,除非您能够跟踪您已经访问过的 ID 并将其传入。

function setCellState(id, visited) {
  if(id === null) {
    return;
  }
  if(visited === undefined) {
    visited = new Set();
  }
  if(visited.has(id)) {
    return;
  }
  visited.add(id);

  board[getBoardPosition(id)].opened = true;

  // getAdjacentCells() will return either an array of objects similar to the one the function takes as an argument or an integer
  let adjacentCells = getAdjacentCells(id);
  // if getAdjacentCells(id) returns a number, add a div to the HTML element with that id
  if (typeof (adjacentCells) === "number") {
        // Removes all other divs, this prevents repetition
        $("#" + id).empty()
          // Appends an empty div
          .append("<div></div>");
  } else if (typeof (adjacentCells) === "object") {
    Object.values(adjacentCells).forEach(id2 => setCellState(id2, visited));
  }

I took the liberty of changing the method name to be more representative of what the method actually does.我冒昧地更改了方法名称以更能代表该方法的实际作用。 I also changed it to start with a single cell's ID, since that simplifies the recursion and that allows the comment around the behavior of getAdjacentCells to provide better context.我还将它更改为从单个单元格的 ID 开始,因为这简化了递归,并且允许围绕getAdjacentCells行为的注释提供更好的上下文。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使这个递归 function 异步? - How can I make this recursive function asynchronous? 如何退出单击 function 或防止 function 在满足条件之前触发 - How can I exit a click function or prevent the function from triggering until a condition is met 如何让casperjs重复循环直到满足某个条件? - How can I make casperjs repeat a loop until a certain condition is met? 如何制作容器 Position:粘性; 直到在视口中满足滚动量 - How can I make a containers Position: sticky; until scroll amount is met in viewport 在满足条件之前不要运行功能 - Do not run function until condition is met 如何在满足条件之前重复 Firestore 查询? - How can I repeat a Firestore query until a condition is met? 如何让代码等到满足条件 x= true 时,请注意我不想使用“setTimeOut” - How can I make a code wait until condition x= true is met , note I don't want to use 'setTimeOut' 我怎么能等到不为空的东西然后运行函数 - How can I wait until something is not null then run the function 如何运行功能,直到达到期望的结果? - How can I run a function until it meets the desired outcome? 如何在前一个函数完成之前进行语句? - How can I make a statement wait until a previous function is finished?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM