Reputation: 23
I am working in C#.
How to combine (sum, plus, minus) these class elements in both lists?
class Attribute
{
public AttributeType WhatAttri;
public float amount;
}
enum AttributeType{
maxhp, str, dex, int, wis,,,,
}
Attribute[] attList1;
Attribute[] attList2;
If specific values are like this,
attList1[0] = new Attribute(AttributeType.maxhp, 6)
attList1[1] = new Attribute(AttributeType.str, 4)
attList1[2] = new Attribute(AttributeType.dex, 3)
attList2[0] = new Attribute(AttributeType.str, 9)
attList2[1] = new Attribute(AttributeType.int, 7)
attList2[2] = new Attribute(AttributeType.wis, 5)
I want final result like this, (attList1 values are added, attList2 values are deducted, and also sum(or minus or plus) duplicated AttributeType)
So at above two lists, AttributeType.str is same, so deduct duplicated attList2[0]'s amount variable's value (9) from attList1[1]'s value (4) and exclude this element from attList2.
So final result should be,
Attribute[] combinedList; (or List<Attribute> combinedList )
combinedList[0] = new Attribute(AttributeType.maxhp, 6)
combinedList[1] = new Attribute(AttributeType.str, -5) (4 - 9)
combinedList[2] = new Attribute(AttributeType.dex, 3)
combinedList[3] = new Attribute(AttributeType.int, -7)
combinedList[4] = new Attribute(AttributeType.wis, -5)
How to achieve this?
Thanks.
Upvotes: 1
Views: 206
Reputation: 1238
var result =
attList2.Select(a => new Attribute(a.WhatAttri, -a.amount)) // line 1
.Concat(attList1) // line 2
.GroupBy(a => a.WhatAttri) // line 3
.Select(g => new Attribute(g.Key, g.Sum(a => a.amount))); // line4
foreach(var a in result)
{
Console.WriteLine($"{a.WhatAttri}: {a.amount}");
}
You want to sum up the counts of the first list and subtract the amounts of the second list. So first I transform the second list to a new list with negative amounts (line 1). then the two lists are joined into one list (line 2). Then the big line is grouped by type (line 3). and then you have a structure of Key and items, where you create new Attributes by using the key and the sum of the amounts (line 4).
Edit: replaced "Union" in line 2 by "Concat" to avoid dropping duplicate values in case there would be a custom comparer method in class Attribute
Upvotes: 1
Reputation: 23
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public enum AttributeType
{
maxhp, str, dex, intel, wis,
}
[System.Serializable]
public class Attribute
{
public AttributeType WhatAttri;
public float amount;
public Attribute(AttributeType type, int a)
{
WhatAttri = type;
amount = a;
}
}
public class LinqTest : MonoBehaviour
{
Attribute[] attList1 = new Attribute[3];
Attribute[] attList2 = new Attribute[3];
void Start()
{
attList1[0] = new Attribute(AttributeType.maxhp, 6);
attList1[1] = new Attribute(AttributeType.str, 4);
attList1[2] = new Attribute(AttributeType.dex, 3);
attList2[0] = new Attribute(AttributeType.str, 9);
attList2[1] = new Attribute(AttributeType.intel, 7);
attList2[2] = new Attribute(AttributeType.wis, 5);
Calcul();
}
void Calcul()
{
var result = attList2
.Select(a => new Attribute(a.WhatAttri, -(int)a.amount)) // line 1
.Union(attList1) // line 2
.GroupBy(a => a.WhatAttri) // line 3
.Select(g => new Attribute(g.Key, g.Sum(a => (int)a.amount))); // line4
foreach (var a in result)
{
Debug.Log($"{a.WhatAttri}: {a.amount}");
}
}
}
This is final result of testing above code by answers. Using Unity engine.
Upvotes: 0
Reputation: 2057
The main issue is that you didn't have positive or negative value in the attributes modifier. How whould you boost those attribute? Once it's fix the solution is easy
Add both list with concat, GroupBy AttributeType, and select the values.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var attributes = new Attribute[] {
new Attribute{WhatAttri=AttributeType.maxhp, amount=6 },
new Attribute{WhatAttri=AttributeType.str, amount=4 },
new Attribute{WhatAttri=AttributeType.dex, amount=3 },
};
//Attribute modifier has to be either positive or negative
var attributesModifier = new Attribute[] {
new Attribute{WhatAttri=AttributeType.str, amount=-9 },
new Attribute{WhatAttri=AttributeType.@int, amount=-7 },
new Attribute{WhatAttri=AttributeType.wis, amount=-5 },
};
var newAttributes = attributes
.Concat(attributesModifier)
.GroupBy(x => x.WhatAttri)
.Select(group =>
new Attribute {
WhatAttri = group.Key,
amount = group.Sum(g => g.amount)
});
newAttributes.Dump();
}
public class Attribute
{
public AttributeType WhatAttri { get; set; }
public float amount { get; set; }
}
public enum AttributeType
{
maxhp, str, dex, @int, wis
}
}
OnLine demo https://dotnetfiddle.net/3C7n7F
Upvotes: 0