副作用最小的递归
Recursion with the least sideeffect
所以我有一棵 children 的人,我只想得到有车的人。如果 child 有车而 parent 没有,我想将 parent 保留在树中。
我认为最好的方法是使用递归函数,它看起来像这样:
private Person CheckPerson(Person person)
{
List<Person> removeList = new List<Person>();
foreach (Person child in Person.Children)
{
if (CheckPerson(child) == null)
{
// I can't remove the children here because
// they are used in the foreach loop
removeList.Add(child);
}
}
foreach (Person removable in removeList)
{
Person.Children.Remove(removable);
}
if (person.Children.Count() > 0)
{
return person;
}
else if (person.cars.Count() > 0)
{
return person;
}
else
{
return null;
}
}
但是这样我确实改变了参数person,我删除了他的children.
我试过的其他方法如下
- return无效
- return 布尔值
- 引用参数
我也试过在没有 return 值的情况下这样做,只是回头看看输入者的结果,但这并没有保存更改。
返回一个布尔值以确定是否应删除 child 有效,但原始方法调用对该布尔值没有任何用处。所以这个方法有副作用,因为 Person -> bool,但我还是换了 person
使用 ref 参数我无法编译,因为我删除了 children 并在那里更改了我的 foreach 循环中的 object。
所以我想知道使用副作用最小的递归方法的最佳方法是什么,或者最佳实践是什么?
如果你只需要测试是否有车可用,你可以使用这个:
public Person CheckPerson(Person person)
{
return person.Cars.Any() || person.Children.Any(x => CheckPerson(x) != null) ? person : null;
}
但我认为你应该 return 一个 IEnumerable<Person>
包含所有有车的人(或者一个 child 有车的人)。
也许是这样的:
public IEnumerable<Person> GetPersonsWithCars(Person person)
{
var personReturned = false;
if (person.Cars.Any())
{
yield return person;
personReturned = true;
}
foreach (var child in person.Children)
{
foreach (var item in GetPersonsWithCars(child))
{
if (!personReturned)
{
yield return person;
personReturned = true;
}
yield return item;
}
}
}
所以我有一棵 children 的人,我只想得到有车的人。如果 child 有车而 parent 没有,我想将 parent 保留在树中。
我认为最好的方法是使用递归函数,它看起来像这样:
private Person CheckPerson(Person person)
{
List<Person> removeList = new List<Person>();
foreach (Person child in Person.Children)
{
if (CheckPerson(child) == null)
{
// I can't remove the children here because
// they are used in the foreach loop
removeList.Add(child);
}
}
foreach (Person removable in removeList)
{
Person.Children.Remove(removable);
}
if (person.Children.Count() > 0)
{
return person;
}
else if (person.cars.Count() > 0)
{
return person;
}
else
{
return null;
}
}
但是这样我确实改变了参数person,我删除了他的children.
我试过的其他方法如下
- return无效
- return 布尔值
- 引用参数
我也试过在没有 return 值的情况下这样做,只是回头看看输入者的结果,但这并没有保存更改。
返回一个布尔值以确定是否应删除 child 有效,但原始方法调用对该布尔值没有任何用处。所以这个方法有副作用,因为 Person -> bool,但我还是换了 person
使用 ref 参数我无法编译,因为我删除了 children 并在那里更改了我的 foreach 循环中的 object。
所以我想知道使用副作用最小的递归方法的最佳方法是什么,或者最佳实践是什么?
如果你只需要测试是否有车可用,你可以使用这个:
public Person CheckPerson(Person person)
{
return person.Cars.Any() || person.Children.Any(x => CheckPerson(x) != null) ? person : null;
}
但我认为你应该 return 一个 IEnumerable<Person>
包含所有有车的人(或者一个 child 有车的人)。
也许是这样的:
public IEnumerable<Person> GetPersonsWithCars(Person person)
{
var personReturned = false;
if (person.Cars.Any())
{
yield return person;
personReturned = true;
}
foreach (var child in person.Children)
{
foreach (var item in GetPersonsWithCars(child))
{
if (!personReturned)
{
yield return person;
personReturned = true;
}
yield return item;
}
}
}