我有一些代码可以生成位置类型和最大数量的输出。
我只想保留这些值的每种组合中的最大值。但是我不确定会允许n个位置的最佳方法。
当前生成数据并将其存储为字符串列表,并在位置之间留有空格。
var locationOutputDistinct = new List<string>
{
"PERSON:2 ",
"PERSON:1 SCOOTER:1 ",
"PERSON:1 BIKE:1 ",
"PERSON:2 BIKE:1 ",
"PERSON:1 BIKE:1 SCOOTER:1 ",
"PERSON:3 ",
"PERSON:3 BIKE:1 ",
"PERSON:4 ",
"PERSON:4 BIKE:1 ",
"PERSON:2 SCOOTER:1 ",
"PERSON:5 ",
"PERSON:3 SCOOTER:1 ",
"PERSON:6 "
};
理想的输出如下所示:
PERSON:1 BIKE:1 SCOOTER:1
PERSON:4 BIKE:1
PERSON:3 SCOOTER:1
PERSON:6
表示您可以有6个人,或者3个人和一辆小型摩托车,或者4个人和一辆自行车,或者1个人,1个自行车和1个滑板车。它们各自类型的最大组合。
最好的方法是什么?
还有其他一些数据集和预期结果。 https://justpaste.it/6cce5
这是一个直观的示例,并解释了我要制作的内容。 https://justpaste.it/4vqu2
答案 0 :(得分:1)
基于2个课程
public class Res{
public string Key;
public int Val;
}
public class Reduced
{
public string Key;
public IEnumerable<Res>[] invalid;
}
您可以使用此代码汇总结果。
var loc =
locationOutputDistinct
.Select(x => x.Trim().Split(' ').ToArray()
.Select(
y => {
var kv = y.Split(':');
return new Res()
{
Key = kv[0],
Val = int.Parse
(kv[1])
};
}).ToArray()).ToArray()
.GroupBy(x =>
String.Join(",",
x.Select(y => y.Key))
);
然后您必须应用归约规则
var reduced =
loc.Select(x => new Reduced() {
Key = x.Key,
invalid =
x.Where(y => loc.Any(ext => ext.Any(xsup =>
y.All(z => xsup.Any(xsupcell => xsupcell.Key == z.Key)) &&
y.All(z =>
z.Val <= xsup
.Where(xsupcell =>
xsupcell.Key == z.Key)
.First().Val) &&
((xsup.Length > y.Length) ||
y.Any(z =>
z.Val < xsup
.Where(xsupcell =>
xsupcell.Key == z.Key)
.First().Val))
))).ToArray()
});
var remain = loc.Select(x => x.Where(y =>
!reduced.Where(r => r.Key == x.Key).SelectMany(r2 => r2.invalid).Any(r3 => r3.All(r4 =>
y.Any(y2 => y2.Key == r4.Key && y2.Val == r4.Val)))));
从您的上一个示例中,我看到您也希望减少扩展的组合y
和扩展的组合(xsup.Length > y.Length
),因此我在上面的代码中包括了最后一个功能。 / p>
这时您需要打开包装并打印结果。
foreach (var x in remain)
Console.WriteLine
(//x.Key+": " +
String.Join("\n",
x.Select(y =>
String.Join(" ",
y.Select(z => z.Key + ":" + z.Val)
))));
从问题的原始顺序中您将获得
PERSON:6
PERSON:3 SCOOTER:1
PERSON:4 BIKE:1
PERSON:1 BIKE:1 SCOOTER:1
和来自
"AM:4 SC:1 ",
"AM:4 WC:1 ",
"AM:4 WC:1 SC:1 ",
"AM:4 WC:2 ",
"AM:4 WC:2 SC:1 ",
"AM:5 ",
"AM:5 WC:1 ",
"AM:6 ",
"AM:6 WC:1 ",
"AM:7 ",
"AM:8 "
你会得到
AM:6 WC:1
AM:4 WC:2 SC:1
AM:8
答案 1 :(得分:0)
以下作品:
var locationOutputDistinct = new List<string>
{
"FRNT:2 REAR:1 ",
"FRNT:2 ROOF:1 ",
"FRNT:2 ROOF:1 REAR:1 ",
"FRNT:3 ",
"FRNT:3 REAR:1 ",
"FRNT:4 ",
"FRNT:4 REAR:1 ",
"FRNT:3 ROOF:1 ",
"FRNT:5 ",
"FRNT:4 ROOF:1 ",
"FRNT:6 ",
"FRNT:5 ROOF:1 ",
"FRNT:7 ",
"FRNT:6 ROOF:1 ",
"FRNT:8 "
};
var parsedData = locationOutputDistinct
.Select(x => x.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(y => new KeyValuePair<string, int>(y.Substring(0, y.IndexOf(":")), int.Parse(y.Substring(y.IndexOf(":") + 1)))).OrderBy(z => z.Key).ToList())
.ToList();
var groups = parsedData
.GroupBy(x => string.Join("^", x.Select(y => y.Key)))
.ToList();
var results = groups.Select(x => x.SelectMany(y => y).GroupBy(z => z.Key).Select(z => new { Key = z.Key, Value = z.Max(a => a.Value)}).ToList()).ToList();
List<string> strings = results.Select(x => string.Join(" ", x.Select(y => y.Key + ":" + y.Value.ToString()))).ToList();
答案 2 :(得分:0)
下面的LINQ查询将为您提供预期的结果。首先,我们将名称按数字进行分组,因为它们将始终相同。然后,我们遍历分组并计算需要匹配的最大和,最后,我们从该组中获得具有匹配和的记录。
var groupedLocation = locationOutputDistinct.GroupBy(x => new string(x.Where(c => !char.IsDigit(c)).ToArray()))
.OrderByDescending(x => x.Key.Length)
.ToList();
foreach(var group in groupedLocation)
{
var maxSum = group.Max(x => x.Where(c => char.IsDigit(c))
.Select(z => char.GetNumericValue(z)).Sum());
var matchingRecord = group.FirstOrDefault(x => x.Where(c => char.IsDigit(c)).Select(z => char.GetNumericValue(z)).Sum() == maxSum);
Console.WriteLine(matchingRecord);
}
输出
答案 3 :(得分:0)
我提供此解决方案的原因是我的输出与您的示例输出不匹配。那是因为我不同意您的输出。
例如,您拥有的一个输出示例提供了以下内容:
OUTPUT:
AM:10 BK:1
AM:8 BK:1 BWC:1
AM:8 BK:1 WC:1
AM:7 BK:1 SC:1
AM:6 BK:1 BWC:2
AM:6 BK:1 BWC:1 WC:1
AM:6 BK:1 WC:2
AM:5 BK:1 BWC:1 SC:1
AM:5 BK:1 WC:1 SC:1
AM:4 BK:1 BWC:2 WC:1
AM:4 BK:1 WC:3
AM:4 BK:1 SC:2
AM:2 BK:1 WC:1 SC:2
但是AM:4 BK:1 WC:3
小于AM:8 BK:1 WC:1
,因此我不认为这两个都是结果,并且有多个示例。话虽如此,这是我的解决方案,它为每种可能的输入组合获取绝对最大值。
执行:
// Get all the `keys` in the location output
var keys = GetKeys(locationOutputDistinct);
// Get the possible combinations of keys
var combinations = GetCombination(keys);
var maxCombos = new List<string>();
foreach (var combo in combinations)
{
var maxOfCombo = GetMaxOfCombo(locationOutputDistinct, combo);
if (maxOfCombo.Any())
{
maxCombos.AddRange(maxOfCombo);
}
}
maxCombos = maxCombos.Distinct().ToList();
maxCombos.Sort();
foreach (var maxCombo in maxCombos)
{
Console.WriteLine(maxCombo);
}
以及支持方法:
/// <summary>
/// Get the keys from the input and return it in a `;` delimited string
/// </summary>
/// <param name="vals">Input list</param>
/// <returns></returns>
public static List<string> GetKeys(List<string> vals)
{
var keys = new List<string>();
foreach (var grouping in vals)
{
var parameters = grouping.Split(' ');
foreach (var parameter in parameters)
{
var paramVals = parameter.Split(':');
var label = paramVals[0].Trim();
if (!string.IsNullOrEmpty(label) && !keys.Contains(label))
{
keys.Add(label);
}
}
}
return keys;
}
/// <summary>
/// Take all the keys and return all possible combinations of them
/// </summary>
/// <param name="list">List of keys</param>
/// <returns></returns>
public static List<string> GetCombination(List<string> list)
{
var combos = new List<string>();
var comb = "";
double count = Math.Pow(2, list.Count);
for (int i = 1; i <= count - 1; i++)
{
var sep = "";
string str = Convert.ToString(i, 2).PadLeft(list.Count, '0');
for (int j = 0; j < str.Length; j++)
{
if (str[j] == '1')
{
comb += sep + list[j];
sep = ";";
}
}
combos.Add(comb);
comb = "";
}
return combos;
}
/// <summary>
/// Return the combinations that have the largest values
/// </summary>
/// <param name="source">String list of input</param>
/// <param name="combo">`;` delimited keys you're checking</param>
/// <returns></returns>
public static List<string> GetMaxOfCombo(List<string> source, string combo)
{
var comboKeys = combo.Split(';');
var matchingCombos = source.Where(s => comboKeys.All(a => s.IndexOf(a) != -1) && s.Trim().Split(' ').Length == comboKeys.Count());
// Return empty set if there were none
if (!matchingCombos.Any())
{
return new List<string>();
}
var comboValues = matchingCombos.Select(mc => new
{
// Get the value sum of the individual keys
value = mc.Split(' ').Where(w => !string.IsNullOrEmpty(w.Trim())).Sum(s => int.Parse(string.Concat(s.Where(c => char.IsDigit(c))))),
label = mc
});
// Get the max value
var max = comboValues.Max(m => m.value);
// Get all that have the same max
var maxCombos = comboValues.Where(f => f.value == max);
if (!maxCombos.Any())
{
return new List<string>();
}
return maxCombos.Select(s => s.label).ToList();
}
这是一个有效的示例:https://dotnetfiddle.net/mwpkMO