C#帮助创建一个一维数组,该数组来自一个包含类数据的数组。

huangapple go评论75阅读模式
英文:

C# help creating a 1d array from an array of class data

问题

我需要从一个类中以不同顺序提取数据 - 我认为我需要使用反射,但不确定如何设置它。

在我的主线程中:

我需要将数据连接在一起,但用户可以选择顺序 -  volumebidask 可能是:

[10, 20, 17, 123, 23, 78, 125, 27, 92]

或者如果他们想要 bidvolumeask 可能是:

[123, 23, 78, 10, 20, 17, 125, 27, 92]

使用 linq,我可以硬编码它:

var vol = test.Select(s => s.volume);
var bd = test.Select(s => s.bid);
var ak = test.Select(s => s.ask);
var output = vol.Concat(bd).Concat(ak);

如何使它可以从一个不同的数组中调用 volumebidask,并且可以按照用户的喜好进行排序?
英文:

Need some help pulling data out of a class in different orders - think I need reflection but not sure how to set it up.

public class Strike
{
    public float volume { get; private set; }
    public float bid { get; private set; }
    public float ask { get; private set; }
}

In my main thread:

var test = new Strike()
{
    volume = 10,
    bid = 123,
    ask = 125
},
{
    volume = 20,
    bid = 23,
    ask = 27
},
{
    volume = 17,
    bid = 78,
    ask = 92
}

I need to concat the data together but the user can select which order - i.e. volume, bid, ask would be

[10, 20, 17, 123, 23, 78, 125, 27, 92]

or if they want bid, volume ask

[123, 23, 78, 10, 20, 17, 125, 27, 92]

Using linq I can hard code it

var vol = test.Select(s => s.volume);
var bd = test.Select(s => s.bid);
var ak = test.Select(s => s.ask);
var output = vol.Concat(bd).Concat(ak);

How do i make it so that I can call the volume, bid, ask from a different array that I can order how the user would like

答案1

得分: 2

我强烈怀疑你一开始就没有使用正确的数据结构。鉴于你想要的结果,我不确定类是否是最佳选择。

然而,你可以使用反射来实现你的需求。

IEnumerable<float> BuildList(Strike[] strikes, params string[] properties)
{
    Type type = typeof(Strike);
    List<PropertyInfo> propertyInfos = new();

    // 为每个属性构建 PropertyInfos
    foreach (string property in properties)
    {
        PropertyInfo? info = type.GetProperty(property, BindingFlags.Public | BindingFlags.Instance);
        if (info != null)
            propertyInfos.Add(info);
    }

    // 构建结果列表
    for (int i = 0; i < propertyInfos.Count; i++)
    {
        for (int j = 0; j < strikes.Length; j++)
        {
            if (propertyInfos[i].GetValue(strikes[j]) is float f)
                yield return f;
        }
    }
}

你可以像这样调用上述方法:

BuildList(test, "bid", "volume", "ask");
英文:

I strongly suspect you are not using the correct data structures to begin with. Given the results you want, I'm not sure classes are the best choice.

However, you could do what you want using reflection.

IEnumerable&lt;float&gt; BuildList(Strike[] strikes, params string[] properties)
{
	Type type = typeof(Strike);
	List&lt;PropertyInfo&gt; propertyInfos = new();

    // Build PropertyInfos for each property
	foreach (string property in properties)
	{
		PropertyInfo? info = type.GetProperty(property, BindingFlags.Public | BindingFlags.Instance);
		if (info != null)
			propertyInfos.Add(info);
	}

    // Build resulting list
	for (int i = 0; i &lt; propertyInfos.Count; i++)
	{
		for (int j = 0; j &lt; strikes.Length; j++)
		{
			if (propertyInfos[i].GetValue(strikes[j]) is float f)
				yield return f;
		}
	}
}

You can call the above method like this:

BuildList(test, &quot;bid&quot;, &quot;volume&quot;, &quot;ask&quot;);

答案2

得分: 1

以下是您提供的代码的中文翻译部分:

这是没有反射的非常简单的代码:

IEnumerable<float> BuildList(Strike[] strikes, params string[] properties)
{
    var map = new Dictionary<string, Func<Strike, float>>()
    {
        { "volume", s => s.volume },
        { "bid", s => s.bid },
        { "ask", s => s.ask },
    };

    return
        from property in properties
        from strike in strikes
        select map[property](strike);
}

如果我运行这个代码:

var test = new[]
{
    new Strike()
    {
        volume = 10,
        bid = 123,
        ask = 125
    },
    new Strike()
    {
        volume = 20,
        bid = 23,
        ask = 27
    },
    new Strike()
    {
        volume = 17,
        bid = 78,
        ask = 92
    }
};

Console.WriteLine(
    String.Join(
        ", ",
        BuildList(test, "volume", "ask", "bid")));

我得到 `10, 20, 17, 125, 27, 92, 123, 23, 78`。
英文:

It's very simple without reflection:

IEnumerable&lt;float&gt; BuildList(Strike[] strikes, params string[] properties)
{
	var map = new Dictionary&lt;string, Func&lt;Strike, float&gt;&gt;()
	{
		{ &quot;volume&quot;, s =&gt; s.volume },
		{ &quot;bid&quot;, s =&gt; s.bid },
		{ &quot;ask&quot;, s =&gt; s.ask },
	};
	
	return
		from property in properties
		from strike in strikes
		select map[property](strike);
}

If I run this:

var test = new[]
{
	new Strike()
	{
		volume = 10,
		bid = 123,
		ask = 125
	},
	new Strike()
	{
		volume = 20,
		bid = 23,
		ask = 27
	},
	new Strike()
	{
			volume = 17,
		bid = 78,
		ask = 92
	}
};

Console.WriteLine(
	String.Join(
		&quot;, &quot;,
		BuildList(test, &quot;volume&quot;, &quot;ask&quot;, &quot;bid&quot;)));

I get 10, 20, 17, 125, 27, 92, 123, 23, 78.

答案3

得分: 0

你可以使用反射(reflection.first)创建一个按顺序排列的字符串列表,并使用 foreach 进行连接。

只需在设置类中输入所需的列表(例如:ask、bid、volume)。

List<string> strings = new List<string>() { "ask", "bid", "volume" };
List<string> list = new List<string>();

foreach (var test in strings)
{
    list.AddRange(tests.Select(x => x.GetType().GetProperty(test).GetValue(x, null).ToString()).ToArray());
}

在下面的代码中,我将整个代码与测试数据示例放在一起,并显示输出。

var tests = new List<Strike>();
tests.Add(new Strike() { volume = 10, bid = 123, ask = 125 });
tests.Add(new Strike() { volume = 20, bid = 23, ask = 27 });
tests.Add(new Strike() { volume = 17, bid = 78, ask = 92 });

List<string> strings = new List<string>() { "ask", "bid", "volume" };
List<string> list = new List<string>();

foreach (var test in strings)
{
    list.AddRange(tests.Select(x => x.GetType().GetProperty(test).GetValue(x, null).ToString()).ToArray());
}

foreach (var item in list)
{
    Console.WriteLine(item);
}
英文:

You can Use reflection.first Create List order (strings ) and use foreach to Concat

You just need to enter the desired list (according to the order) in the settings class(Example : ask,bid,volume)


List&lt;string&gt; strings = new List&lt;string&gt;() { &quot;ask&quot;, &quot;bid&quot;, &quot;volume&quot; };
List&lt;string&gt; list = new List&lt;string&gt;();

foreach (var test in strings)
{
    list.AddRange(tests.Select(x =&gt; x.GetType().GetProperty(test).GetValue(x, null).ToString()).ToArray());
}

In the code below, I put the whole code with a test data sample and display the output

var tests = new List&lt;Strike&gt;();
tests.Add(new Strike(){ volume = 10,  bid = 123,  ask = 125 });
tests.Add(new Strike(){ volume = 20, bid = 23,ask = 27});
tests.Add(new Strike(){ volume = 17, bid = 78,ask = 92});

List&lt;string&gt; strings = new List&lt;string&gt;() { &quot;ask&quot;, &quot;bid&quot;, &quot;volume&quot; };
List&lt;string&gt; list = new List&lt;string&gt;();

foreach (var test in strings)
{
    list.AddRange(tests.Select(x =&gt; x.GetType().GetProperty(test).GetValue(x, null).ToString()).ToArray());
}

foreach (var item in list)
{
    Console.WriteLine(item);
}

huangapple
  • 本文由 发表于 2023年6月1日 07:30:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76377853.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定