我有一个行为类似于旋转木马的集合,即:最后一项之后是第一项。在这个集合(List of IdentifiedAnimal)中,有一对总是在一起的值(哺乳动物)。他们甚至可以是第一个和最后一个。
我的目标是找到不是该对中另一项(其他哺乳动物)的一项(作为参数传递)的最近邻居。即:如果我通过 Dog,则它不能是 Cat,反之亦然。
目前我的算法似乎运行良好,但可能存在错误。几乎所有案例的测试都通过了。尽管如此,我想知道是否有更好、更安全的方法来找到给定条件下的邻居,而不涉及如此复杂的算法。对逻辑的改进也表示赞赏。 只是强调一下,狗和猫将永远在一起,彼此(哺乳动物)的邻居。
public Animal GetClosestAnimalNotMammal(IEnumerable<IdentifiedAnimal> identifiedAnimals, Animal currentMammal)
{
Animal otherMammal = (currentMammal == Animal.Dog) ? Animal.Cat : Animal.Dog;
List<IdentifiedAnimal> animalsList = identifiedAnimals.ToList();
int currentIndex = animalsList.FindIndex(c => c.Animal == currentMammal);
int lastIndex = animalsList.IndexOf(animalsList.LastOrDefault());
Dictionary<IdentifiedAnimal, int> animalIndexes = animalsList
.Where(a => a.Animal != otherMammal && a.Animal != currentMammal)
.ToDictionary(identifiedAnimal => identifiedAnimal, identifiedAnimal => animalsList.FindIndex(x => x.Animal == identifiedAnimal.Animal));
int closestIndex = int.MaxValue;
int maxDistance = int.MaxValue;
foreach (KeyValuePair<IdentifiedAnimal, int> animalIndex in animalIndexes)
{
int usedDistance;
if ((animalIndex.Value + currentIndex > lastIndex) && (currentIndex - animalIndex.Value > 0) && currentIndex != lastIndex)
{
usedDistance = Math.Abs((animalsList.Count - (animalIndex.Value + currentIndex)) -
Math.Abs(animalIndex.Value - currentIndex));
}
else if ((animalIndex.Value + currentIndex == lastIndex) && !(currentIndex - animalIndex.Value > 0 && currentIndex != lastIndex))
{
usedDistance = Math.Abs(animalsList.Count - (animalIndex.Value + currentIndex));
}
else
{
usedDistance = Math.Abs(animalIndex.Value - currentIndex);
}
if (usedDistance < maxDistance)
{
closestIndex = animalIndex.Value;
maxDistance = usedDistance;
}
}
return animalsList[closestIndex].Animal;
}
public enum Animal
{
Alligator,
Dog,
Cat,
Fish,
Bird,
Snake
}
public class IdentifiedAnimal
{
public string Id { get; set; }
public Animal Animal { get; set; }
}
测试
[TestClass]
public class UnitTest1
{
private readonly List<IdentifiedAnimal> _identifiedAnimals = new List<IdentifiedAnimal>();
[TestMethod]
public void TestMethod01()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
var expectedAnimal = Animal.Fish;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Cat);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
[TestMethod]
public void TestMethod02()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
var expectedAnimal = Animal.Alligator;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Dog);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
[TestMethod]
public void TestMethod03()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
var expectedAnimal = Animal.Bird;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Dog);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
[TestMethod]
public void TestMethod04()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
var expectedAnimal = Animal.Alligator;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Cat);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
[TestMethod]
public void TestMethod05()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
var expectedAnimal = Animal.Snake;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Dog);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
[TestMethod]
public void TestMethod06()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
var expectedAnimal = Animal.Snake;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Dog);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
[TestMethod]
public void TestMethod07()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
var expectedAnimal = Animal.Bird;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Dog);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
[TestMethod]
public void TestMethod08()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
var expectedAnimal = Animal.Snake;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Dog);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
[TestMethod]
public void TestMethod09()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
var expectedAnimal = Animal.Alligator;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Cat);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
[TestMethod]
public void TestMethod10()
{
// Arrange
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "ASO", Animal = Animal.Cat});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "XYZ", Animal = Animal.Dog});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KLD", Animal = Animal.Alligator});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "LOL", Animal = Animal.Fish});
_identifiedAnimals.Add(new IdentifiedAnimal() {Id = "KJL", Animal = Animal.Bird});
_identifiedAnimals.Add(new IdentifiedAnimal() { Id = "QPO", Animal = Animal.Snake });
var expectedAnimal = Animal.Snake;
// Act
var closestAnimal = new AnimalFinder().GetClosestAnimalNotMammal(_identifiedAnimals, Animal.Cat);
// Assert
Assert.AreEqual(expectedAnimal, closestAnimal);
}
}
最佳答案
没有讽刺的意思,但是,这个问题不是更容易解决吗?我很难理解为什么每个人都需要字典等。也许我误解了什么。
public static bool TryFindNearestTo<T>
(this IList<T> source,
T item,
T itemToExcludeFromSearch,
out T nearest)
{
var indexOfItem = source.IndexOf(item);
if (indexOfItem < 0)
{
//item is not found in source. Search fails.
nearest = default(T);
return false;
}
var indexAfter = indexOfItem == source.Count - 1 ?
0 :
indexOfItem + 1;
var indexBefore = indexOfItem == 0 ?
source.Count - 1 :
indexOfItem - 1;
//Assert preconditions
Debug.Assert(source[indexAfter].Equals(itemToExcludeFromSearch) ||
source[indexBefore].Equals(itemToExcludeFromSearch));
nearest = source[indexAfter].Equals(itemToExcludeFromSearch) ?
source[indexBefore] :
source[indexAfter];
return true;
}
您当前的问题定义不完整。如果出现以下情况,该方法应该做什么:
- 在
source
中找不到指定的item
。 - 如果没有邻居将项目从搜索中排除,会发生什么情况?
如果这两种情况不可能发生,那么您应该在您的代码中断言它们,因为这是一个必须满足的先决条件,该方法才能正常工作。如果他们的条件是可能的,那么你需要验证它们并在不满足时返回一些合理的东西。就我而言,为了便于说明,我将两种情况混为一谈:
TrySomething
模式,其中返回值指示搜索是否成功,结果是out
参数,解决了第一个问题。Debug.Assert
解决了后一个问题。
关于c# - 为相同类型的一对(循环列表)在轮播列表中查找不同类型的邻居,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48112516/