C# LINQ 合并两个分手
C# LINQ to merge two breakup
我正在寻找简单的 LINQ 来解决这个问题:
string[] breakups = new[]
{
"YQ:50/BF:50/YR:50",
"YQ:50/SR:50",
"YQ:50/BF:50/YR:50",
"XX:00 .... and so on"
};
// LINQ expression
string expectedResult = "YQ:150/BF:100/YR:100/SR:50";
我的备选方案如下
public static string CalcRTBreakup(string pstrBreakup)
{
string lstrBreakup = pstrBreakup;
try
{
string[] lstrArrRB = lstrBreakup.Split('@');
string[] lstrArrBreakupSplit = new string[lstrBreakup.Split('@')[0].Split('|').Length];
for (int count = 0; count < lstrArrRB.Length; count++)
{
string[] lstrArrtemp = lstrArrRB[count].Split('|');
for (int countinner = 0; countinner < lstrArrtemp.Length; countinner++)
{
if (string.IsNullOrEmpty(lstrArrBreakupSplit[countinner]))
{
if (string.IsNullOrEmpty(lstrArrtemp[countinner]))
continue;
lstrArrBreakupSplit[countinner] = lstrArrtemp[countinner];
}
else
{
if (string.IsNullOrEmpty(lstrArrtemp[countinner]))
continue;
lstrArrBreakupSplit[countinner] += "/" + lstrArrtemp[countinner];
}
}
}
for (int count = 0; count < lstrArrBreakupSplit.Length; count++)
{
if (string.IsNullOrEmpty(lstrArrBreakupSplit[count]))
continue;
lstrArrBreakupSplit[count] = CalcRTBreakupDict(lstrArrBreakupSplit[count].TrimEnd('/')).TrimEnd('/');
}
lstrBreakup = string.Empty;
foreach (string strtemp in lstrArrBreakupSplit)
{
lstrBreakup += strtemp + '|';
}
return lstrBreakup;
}
catch (Exception)
{
return "";
}
}
public static string CalcRTBreakupDict(string pstrBreakup)
{
string lstrBreakup = pstrBreakup;
Dictionary<string, double> ldictDreakup = new Dictionary<string, double>();
try
{
lstrBreakup = lstrBreakup.TrimEnd('/').Trim();
string[] lstrArrBreakup = lstrBreakup.Split('/');
foreach (string strBr in lstrArrBreakup)
{
string[] lstrBreakupCode = strBr.Split(':');
if (!ldictDreakup.Keys.Contains(lstrBreakupCode[0]))
{
double lintTemp = 0; double.TryParse(lstrBreakupCode[1], out lintTemp);
ldictDreakup.Add(lstrBreakupCode[0], lintTemp);
}
else
{
double lintTemp = 0; double.TryParse(lstrBreakupCode[1], out lintTemp);
lintTemp = lintTemp + ldictDreakup[lstrBreakupCode[0]];
ldictDreakup.Remove(lstrBreakupCode[0]);
ldictDreakup.Add(lstrBreakupCode[0], lintTemp);
}
}
lstrBreakup = string.Empty;
foreach (string dictKey in ldictDreakup.Keys)
{
lstrBreakup += dictKey + ":" + ldictDreakup[dictKey] + "/";
}
return lstrBreakup;
}
catch (Exception)
{
return pstrBreakup;
}
}
查看结果,我假设您在分号之后添加的值与分号之前的标签匹配。
它可以被视为一个有趣的小测验,也许更适合另一个 stackexchange 站点,但无论如何。
这可以通过一个简单(但不是很短)的 linq 表达式来实现:
breakups
.Select(c => c.Split('/'))
.SelectMany(c => c)
.Select(c => new
{
Label = c.Split(':')[0],
Value = Convert.ToInt32(c.Split(':')[1])
})
.GroupBy(c => c.Label)
.Select(c => new
{
Label = c.Key,
Value = c.Sum(x => x.Value)
})
.OrderByDescending(c => c.Value)
.Select(c => c.Label + ":" + c.Value)
.Aggregate((s1,s2) => s1 + "/" + s2)
string[] breakups =
{
"YQ:50/BF:50/YR:50",
"YQ:50/SR:50",
"YQ:50/BF:50/YR:50",
"XX:00"
};
var groups = from line in breakups // these are our items in the array
from item in line.Split('/') // each one will be split up at '/'
let pair = item.Split(':') // each pair is split at ':'
let key = pair[0] // our key is the first item...
let value = int.Parse(pair[1]) // and the value is the second
group value by key // let's group by key
into singleGroup
let sum = singleGroup.Sum() // and build each group's sum
where sum > 0 // filter out everything <= 0
select singleGroup.Key + ":" + sum; // and build the string
var result = string.Join("/", groups);
var sums = breakups.SelectMany(breakup => breakup.Split('/'))
.Select(s => new { Code = s.Substring(0, 2), Value = int.Parse(s.Substring(2)) })
.GroupBy(pair => pair.Code)
.Select(group => string.Format("{0}/{1}", group.Key, group.Sum(x => x.Value)));
string result = string.Join("/", sums);
代码可能包含语法错误,因为我没有测试它。
如果您不需要按值排序,您可以简单地执行
var res = string.Join("/", breakups
.SelectMany(m => m.Split('/'))
.Select(x => x.Split(':'))
.GroupBy(m => m[0])
.Select(m => string.Format("{0}:{1}", m.Key, m.Sum(g => Int32.Parse(g[1])))));
如需订购
var res = string.Join("/", breakups
.SelectMany(m => m.Split('/'))
.Select(x => x.Split(':'))
.GroupBy(m => m[0])
.Select(m => new
{
key = m.Key,
val = m.Sum(g => Int32.Parse(g[1]))
})
.OrderByDescending(m => m.val)
.Select(m => string.Format("{0}:{1}", m.key, m.val)));
我正在寻找简单的 LINQ 来解决这个问题:
string[] breakups = new[]
{
"YQ:50/BF:50/YR:50",
"YQ:50/SR:50",
"YQ:50/BF:50/YR:50",
"XX:00 .... and so on"
};
// LINQ expression
string expectedResult = "YQ:150/BF:100/YR:100/SR:50";
我的备选方案如下
public static string CalcRTBreakup(string pstrBreakup)
{
string lstrBreakup = pstrBreakup;
try
{
string[] lstrArrRB = lstrBreakup.Split('@');
string[] lstrArrBreakupSplit = new string[lstrBreakup.Split('@')[0].Split('|').Length];
for (int count = 0; count < lstrArrRB.Length; count++)
{
string[] lstrArrtemp = lstrArrRB[count].Split('|');
for (int countinner = 0; countinner < lstrArrtemp.Length; countinner++)
{
if (string.IsNullOrEmpty(lstrArrBreakupSplit[countinner]))
{
if (string.IsNullOrEmpty(lstrArrtemp[countinner]))
continue;
lstrArrBreakupSplit[countinner] = lstrArrtemp[countinner];
}
else
{
if (string.IsNullOrEmpty(lstrArrtemp[countinner]))
continue;
lstrArrBreakupSplit[countinner] += "/" + lstrArrtemp[countinner];
}
}
}
for (int count = 0; count < lstrArrBreakupSplit.Length; count++)
{
if (string.IsNullOrEmpty(lstrArrBreakupSplit[count]))
continue;
lstrArrBreakupSplit[count] = CalcRTBreakupDict(lstrArrBreakupSplit[count].TrimEnd('/')).TrimEnd('/');
}
lstrBreakup = string.Empty;
foreach (string strtemp in lstrArrBreakupSplit)
{
lstrBreakup += strtemp + '|';
}
return lstrBreakup;
}
catch (Exception)
{
return "";
}
}
public static string CalcRTBreakupDict(string pstrBreakup)
{
string lstrBreakup = pstrBreakup;
Dictionary<string, double> ldictDreakup = new Dictionary<string, double>();
try
{
lstrBreakup = lstrBreakup.TrimEnd('/').Trim();
string[] lstrArrBreakup = lstrBreakup.Split('/');
foreach (string strBr in lstrArrBreakup)
{
string[] lstrBreakupCode = strBr.Split(':');
if (!ldictDreakup.Keys.Contains(lstrBreakupCode[0]))
{
double lintTemp = 0; double.TryParse(lstrBreakupCode[1], out lintTemp);
ldictDreakup.Add(lstrBreakupCode[0], lintTemp);
}
else
{
double lintTemp = 0; double.TryParse(lstrBreakupCode[1], out lintTemp);
lintTemp = lintTemp + ldictDreakup[lstrBreakupCode[0]];
ldictDreakup.Remove(lstrBreakupCode[0]);
ldictDreakup.Add(lstrBreakupCode[0], lintTemp);
}
}
lstrBreakup = string.Empty;
foreach (string dictKey in ldictDreakup.Keys)
{
lstrBreakup += dictKey + ":" + ldictDreakup[dictKey] + "/";
}
return lstrBreakup;
}
catch (Exception)
{
return pstrBreakup;
}
}
查看结果,我假设您在分号之后添加的值与分号之前的标签匹配。
它可以被视为一个有趣的小测验,也许更适合另一个 stackexchange 站点,但无论如何。
这可以通过一个简单(但不是很短)的 linq 表达式来实现:
breakups
.Select(c => c.Split('/'))
.SelectMany(c => c)
.Select(c => new
{
Label = c.Split(':')[0],
Value = Convert.ToInt32(c.Split(':')[1])
})
.GroupBy(c => c.Label)
.Select(c => new
{
Label = c.Key,
Value = c.Sum(x => x.Value)
})
.OrderByDescending(c => c.Value)
.Select(c => c.Label + ":" + c.Value)
.Aggregate((s1,s2) => s1 + "/" + s2)
string[] breakups =
{
"YQ:50/BF:50/YR:50",
"YQ:50/SR:50",
"YQ:50/BF:50/YR:50",
"XX:00"
};
var groups = from line in breakups // these are our items in the array
from item in line.Split('/') // each one will be split up at '/'
let pair = item.Split(':') // each pair is split at ':'
let key = pair[0] // our key is the first item...
let value = int.Parse(pair[1]) // and the value is the second
group value by key // let's group by key
into singleGroup
let sum = singleGroup.Sum() // and build each group's sum
where sum > 0 // filter out everything <= 0
select singleGroup.Key + ":" + sum; // and build the string
var result = string.Join("/", groups);
var sums = breakups.SelectMany(breakup => breakup.Split('/'))
.Select(s => new { Code = s.Substring(0, 2), Value = int.Parse(s.Substring(2)) })
.GroupBy(pair => pair.Code)
.Select(group => string.Format("{0}/{1}", group.Key, group.Sum(x => x.Value)));
string result = string.Join("/", sums);
代码可能包含语法错误,因为我没有测试它。
如果您不需要按值排序,您可以简单地执行
var res = string.Join("/", breakups
.SelectMany(m => m.Split('/'))
.Select(x => x.Split(':'))
.GroupBy(m => m[0])
.Select(m => string.Format("{0}:{1}", m.Key, m.Sum(g => Int32.Parse(g[1])))));
如需订购
var res = string.Join("/", breakups
.SelectMany(m => m.Split('/'))
.Select(x => x.Split(':'))
.GroupBy(m => m[0])
.Select(m => new
{
key = m.Key,
val = m.Sum(g => Int32.Parse(g[1]))
})
.OrderByDescending(m => m.val)
.Select(m => string.Format("{0}:{1}", m.key, m.val)));