我正在使用MCP2515(CAN收发器)进行项目开发,该芯片的功能之一是可以通过应用规则(掩码)仅允许特定范围的数据通过过滤器来过滤ID。我最多可以有6个不同的过滤器。在我正在编码的应用程序中,我解析一个DBC文件以选择我想要接收的信号。如果我有6个或更少的信号,我可以为这些信号中的每一个制定一个“通过规则”,但是如果我有6个以上的信号,则需要创建包含所有所需ID的规则。理想情况下,每个组将合并尽可能小的数据范围。我希望可以自动计算出它,因此我需要创建一种算法来重新组合我的ID。
例如,如果我选择了以下ID: 32、154、157、160、354、363、680、682、841、845、871、932、936、940
我的数据组将是[32],[154、157、160],[354、363],[680、682],[841、845、871],[932、936、940]。
这是我现在拥有的代码,但是在处理范围的两端时遇到麻烦(在上述情况下:32和940)。
private void getMasks()
{
List<List<uint>> fields = new List<List<uint>>();
uint spectrum = 0;
uint chunkSize = 0;
IDs.Sort();
spectrum = IDs.Last() - IDs.First();
//Gets the sixth of my whole data range for a first grouping
chunkSize = (uint)Math.Ceiling(((double)spectrum / 6));
//Regroups data in the 6 ranges
for(int i = 0; i < 6; i++)
{
fields.Add(new List<uint>());
foreach (uint id in IDs)
{
if (id >= ((i * chunkSize) + IDs.First()) && id < (((i + 1) * chunkSize) - 1) + IDs.First())
fields[i].Add(id);
}
}
//If a range doesn't have data, removes it
for (int j = 0; j < fields.Count; j++)
if (fields[j].Count == 0)
{
fields.RemoveAt(j);
j--;
}
//Reorganize the data in fields to have the smallest range possible in the subgroups
for(int k = 0; k < fields.Count - 1; k++)
{
//MY PROBLEM IS IN THE NEXT TWO LOOPS
//If the last data in a group is closer from the first data of the next group than from the second last of its own group, moves it to the next group
while(fields[k].Count >= 2 && fields[k+1].Count > 0 && ((fields[k][fields[k].Count -1] - fields[k][fields[k].Count - 2]) > (fields[k+1][fields[k+1].Count -1] - fields[k][fields[k].Count - 1])))
{
fields[k + 1].Add(fields[k].Last());
fields[k].RemoveAt(fields[k].Count - 1);
}
//If the first data in a group is closer to the last data of the last group than to the second data of its own group, moves it to the last group.
while (fields[k].Count > 0 && fields[k + 1].Count >= 2 && ((fields[k+1][1] - fields[k+1][0]) > (fields[k].Last() - fields[k+1][0])))
{
fields[k].Add(fields[k+1][0]);
fields[k+1].RemoveAt(0);
}
}
//Some other code to find the masks to apply
}
有人可以给我一些提示或示例,说明如何在尽可能小的范围内重新组合数据吗?
谢谢
阿尔弗雷德
答案 0 :(得分:1)
这是您的列表,其中包含到下一项的计算出的“距离”:
32(122), 154(3), 157(3), 160(194), 354(9), 363(317), 680(2), 682(159), 841(4), 845(26), 871(61), 932(4), 936(4), 940()
此处同一列表按“距离”降序排列:
363(317), 160(194), 682(159), 32(122), 871(61), 845(26), 354(9), 841(4), 932(4), 936(4), 154(3), 157(3), 680(2), 940()
您需要什么-服用前5项:
363(317), 160(194), 682(159), 32(122), 871(61)
并在这些项目之后“拆分”原始列表:
32(122) // split 4
154(3), 157(3), 160(194) // split 2
354(9), 363(317) // split 1
680(2), 682(159) // split 3
841(4), 845(26), 871(61) // split 5
932(4), 936(4), 940()
它将给您6个小组(您最多削减了5个空格)
答案 1 :(得分:0)
在代码中:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<int> signals = new List<int>() { 680, 841, 154, 940, 160, 157, 936, 354, 363, 682, 871, 932, 845, 32};
signals.Sort();
List<GapData> gapsData = new List<GapData>();
for(int i = 0; i < signals.Count - 1; i++)
{
GapData newGap = new GapData() { Index = i, Span = signals[i + 1] - signals[i] };
gapsData.Add(newGap);
}
gapsData.Sort();
gapsData = gapsData.Take(5).ToList(); //Keep 5 biggest gaps
gapsData = gapsData.OrderBy(i => i.Index).ToList(); //sort on index
List<List<int>> groupedList = new List<List<int>>();
int index = 0;
List<int> currentGroup = new List<int>();
groupedList.Add(currentGroup);
for(int i = 0; i < signals.Count; i++)
{
if (index < 5 && gapsData[index].Index < i)
{
currentGroup = new List<int>();
groupedList.Add(currentGroup);
index++;
}
currentGroup.Add(signals[i]);
}
}
public class GapData:IComparable<GapData>
{
public GapData()
{
}
public int Index { get; set; }
public int CompareTo(GapData other)
{
return - Span.CompareTo(other.Span);
}
public int Span { get; set; }
}
}
}