Reputation: 95
Actually, the title is confusing me and I'm not even sure if it's correct. I'm with the following issue here: I have a List where each recipe holds a requiredItem[] array (size 15) This required item array can hold items which are required for the recipe. What I'm tring to do is get all the recipes in a seperate list, that use wood in their recipe as one of the required items. For example, a recipe could be to need 10 wood to craft a wooden table. This recipe is within the recipe list. A quick google search made me find the following, but I can't figure out how I can access the requiredItem indexes:
List<Recipe> rec = Main.recipe.ToList();
rec.Select((s, i) => new { i, s })
.Where(t => t.s.requiredItem[indexhere].type == 9)
.Select(t => t.i)
.ToList()
I'm sorry I'm not seeing this, I wouldn't be surprised if the answer is really simple.
Also I tried the following. It doesn't bring up any errors, but it's actually not selecting the recipes.
Item refItem = new Item();
refItem.SetDefaults(ItemID.Wood, false);
List<int> selectWood = new List<int>(rec.Select((r, i) => new { i, r }).Where(x => x.r.requiredItem.ToList().Contains(refItem)).Select(x => x.i).ToList());
ErrorLogger.Log(selectWood.ToArray().ToString());
List<int> indices = new List<int>();
foreach (var indice in selectWood)
{
for (int i = 0; i < Main.recipe[indice].requiredItem.Length; i++)
{
var item = Main.recipe[indice].requiredItem[i];
if (item.type == ItemID.Wood && item.stack >= 10) indices.Insert(0, indice);
}
}
foreach (var indice in indices)
{
++numberRecipesRemoved;
rec.RemoveAt(indice);
}
Upvotes: 1
Views: 91
Reputation: 3634
Yes, it is simple, if I understood your question, you need to show all the recepies that contains wood as required item. So do it like this:
var woodRecipes = recipes.Where(r => r.requiredItems.Contains(wood)).ToList();
Upvotes: 1
Reputation: 3663
I may be misreading the question but it is not totally obvious why you need and index (indexHere
) as an Any()
clause should suffice.
Without details of the Recipe
or requiredItem
it is hard to be sure but the following seems to achieve what you need.
enum MaterialType
{
None,
Wood,
Glass,
Steel,
Cloth
}
class Ingredient
{
public Ingredient(MaterialType type, int amount)
{
Type = type;
Amount = amount;
}
public MaterialType Type { get; }
public int Amount { get; }
}
class Recipe
{
public Recipe(string name, params Ingredient[] ingredients)
: this(name, (IEnumerable<Ingredient>) ingredients)
{
}
public Recipe(string name, IEnumerable<Ingredient> ingredients)
{
Name = name;
Ingredients = ingredients.ToArray();
}
public string Name { get; }
public Ingredient[] Ingredients { get; }
}
[TestClass]
public class FindAllItemsFixture
{
private readonly static IEnumerable<Recipe> AllItemRecipes = new List<Recipe>
{
new Recipe("Sword", new Ingredient(MaterialType.Steel, 3)),
new Recipe("Spear", new Ingredient(MaterialType.Steel, 1), new Ingredient(MaterialType.Wood, 3)),
new Recipe("Table", new Ingredient(MaterialType.Wood, 6)),
new Recipe("Chair", new Ingredient(MaterialType.Wood, 4)),
new Recipe("Flag", new Ingredient(MaterialType.Cloth, 2)),
};
IEnumerable<Recipe> GetAllRecipesUsingMaterial(MaterialType materialType)
{
return AllItemRecipes.Where(r => r.Ingredients.Any(i => i.Type == materialType));
}
[TestMethod]
public void GetAllWoodenRecipes()
{
var expectedNames = new string[] { "Spear", "Table", "Chair" };
var woodenItems = GetAllRecipesUsingMaterial(MaterialType.Wood);
CollectionAssert.AreEqual(expectedNames, woodenItems.Select(i => i.Name).ToArray());
}
[TestMethod]
public void GetAllClothRecipes()
{
var expectedNames = new string[] { "Flag" };
var clothItems = GetAllRecipesUsingMaterial(MaterialType.Cloth);
CollectionAssert.AreEqual(expectedNames, clothItems.Select(i => i.Name).ToArray());
}
}
The important piece is the GetAllRecipesUsingMaterial()
function in the unit test. It selects all the recipes that contain an ingredient of a specified type.
Upvotes: 1