我有这个包含两个字符串列表的对象列表,这两个字符串是链接的,我想对两个列表进行排序valeurs
和ProductUid
取决于价值的顺序。
列表产品:
[
{
"groupBy": "coloris",
"valeurs": [
"Beige",
"Gris clair",
"Anthracite",
"Beige",
"Augusta",
"Venezia"
],
"ProductUid": [
"TEST1",
"TEST2",
"TEST3",
"TEST4",
"TEST5",
"TEST6"
]
},
{
"groupBy": "ref_commercial",
"valeurs": [
"29245",
"51625",
"25269",
"29245",
"72585",
"72584"
],
"ProductUid": [
"TEST1",
"TEST2",
"TEST3",
"TEST4",
"TEST5",
"TEST6"
]
}
]
所以最终的结果会是这样的。
排序结果:
[
{
"groupBy": "coloris",
"valeurs": [
"Anthracite",
"Augusta",
"Beige",
"Beige",
"Gris clair",
"Venezia"
],
"ProductUid": [
"TEST3",
"TEST5",
"TEST1",
"TEST4",
"TEST2",
"TEST6"
]
},
{
"groupBy": "ref_commercial",
"valeurs": [
"25269",
"29245",
"29245",
"51625",
"72584",
"72585"
],
"ProductUid": [
"TEST3",
"TEST1",
"TEST4",
"TEST2",
"TEST6"
"TEST5",
]
}
]
我已经做的是
创建列表产品时
var result = lProd.SelectMany(x => x.Caracteristiques.Distinct(), (parentObj, childnum) =>
new
{
parentObj,
childnum
})
.GroupBy(x => x.childnum.nom)
.Select(x => new
{
groupBy = x.Key,
valeurs = x.Select(z => z.childnum.valeur).OrderBy(q => q), // Sort List Valeurs
ProductUid = x.Select(z => z.parentObj.ProductUid), // Want to do the same sort here
}).Where(sid => OrdredList.Any(si => si == sid.groupBy))
.OrderBy(x => OrdredList.IndexOf(x.groupBy));
我能够对valeurs
列表进行排序,但找不到在产品UID上使用相同的排序的方法,
有没有办法做到这一点?
为了使您的任务更容易,我建议您将对象的结构更改为元组(属性,uid)。即使您不需要排序,我也建议您这样做。
.Select(x => new
{
groupBy = x.Key,
valeursAndUids = x
.Select(z => (Valeur: z.childnum.valeur, Uid: z.parentObj.ProductUid))
.OrderBy(q => q.Valeur)
}
您可以创建一个索引列表,并通过在第一个列表中查找值来对其进行排序,然后使用索引从第二个列表中选择值。假设列表长度相等:
var l1 = new[] {1, 0, 2, 3};
var l2 = new[] {"b", "a", "c", "d"};
var indices = new int[l1.Length];
for (int i = 0; i < indices.Length; i++)
{
indices[i] = i;
}
var sortedIndices = indices.OrderBy(i => l1[i]).ToList();
var l2Sorted = sortedIndices.Select(i => l2[i]).ToList();
var l1Sorted = sortedIndices.Select(i => l1[i]).ToList();
Console.WriteLine(string.Join(", ", l2Sorted));
此程序生成所需的输出:
var json = File.ReadAllText("data.json");
var list = JsonSerializer.Deserialize<List<X>>(json);
foreach(var x in list)
{
var combined = x.valeurs.Zip( x.ProductUid, (valuer, uid) => (valuer, uid) );
var sorted = combined.OrderBy(p => p.valuer);
x.valeurs = sorted.Select( p => p.valuer).ToList();
x.ProductUid = sorted.Select( p => p.uid).ToList();
// Or
// var combined = x.valeurs.Zip(x.ProductUid);
// var sorted = combined.OrderBy(p => p.First);
// x.valeurs = sorted.Select( p => p.First).ToList();
// x.ProductUid = sorted.Select( p => p.Second).ToList();
}
Console.WriteLine(JsonSerializer.Serialize(list, new JsonSerializerOptions()
{
WriteIndented = true
}));
class X {
public List<string> valeurs {get; set; }
public List<string> ProductUid {get; set; }
}
这是一个相对简单的方法来实现这一点:
var x = j.Select(e => {
var map = e.Valeurs.Select((v, i) => (v, i)).OrderBy(t => t.v).Select(t => t.i).ToArray();
return new SomeNamespace.SomeRoot
{
GroupBy = e.GroupBy,
Valeurs = map.Select(i => e.Valeurs[i]).ToArray(),
ProductUid = map.Select(i => e.ProductUid[i]).ToArray(),
};
}
);
j
是原始 JSON 的对象表示形式。我将在答案末尾给出解析它的类。本质上j
是一个2长SomeRoot
数组,一个具有string GroupBy
、string[] Valuers
和string[] ProjectUids
性质的对象。它表示根 json 数组中的对象
我们做的第一件事,在这一行:
var map = e.Valeurs.Select((v, i) => (v, i)).OrderBy(t => t.v).Select(t => t.i).ToArray();
是,对于每个根对象,将e.Valuers
投影到一个元组,该元组包含找到该值的索引,i
。然后我们按值排序v
;这意味着我们有一个排序数组,它记住原始元素的找到位置:Anthracite
位于索引2
但在排序后,数组的第一个元素为(Anthracite, 2)
元组。整个数组如下所示:
[
(Anthracite, 2), <-- now in slot 0 but remembers it used to be in slot 2
(August, 4),
(Beige, 0),
(Beige, 3),
(Gris clair, 1)
(Venezia, 5)
]
这种"对它在哪里的记忆"将在以后有用。我们接下来要做的是扔掉Anthracite
等,只保留2
等
这意味着map
是一个整数数组,运行方式类似于[2,4,0,3,1,5]
如果您按此顺序(2,4,0,3,1,5)访问原始评估器数组,则按顺序获得颜色,无烟煤色,八月色,米色,米色。
..因此,您还可以使用相同的映射数组来访问ProjectUids,以相同的顺序获取它们,2,4,0,3,1,5
因此,您的新评估器和ProjectUid数组将变为:
Valeurs = map.Select(i => e.Valeurs[i]).ToArray(),
ProductUid = map.Select(i => e.ProductUid[i]).ToArray(),
你可以把它想象成 *,因为map[0] == 2
原始数组中索引 2 中的内容现在位于排序数组的索引 0 中。地图数组本质上映射了"它需要的位置:它实际在哪里">
要更改排序依据,请更改.OrderBy(t => t.v)
-t
是v
元组,原始评估器值和i
,找到它的索引。
以下是从 JSON 到要求的完整代码,包括用于解析 json 的类:
//impl
var s =
@"[
{
""groupBy"": ""coloris"",
""valeurs"": [
""Beige"",
""Gris clair"",
""Anthracite"",
""Beige"",
""Augusta"",
""Venezia""
],
""ProductUid"": [
""TEST1"",
""TEST2"",
""TEST3"",
""TEST4"",
""TEST5"",
""TEST6""
]
},
{
""groupBy"": ""ref_commercial"",
""valeurs"": [
""29245"",
""51625"",
""25269"",
""29245"",
""72585"",
""72584""
],
""ProductUid"": [
""TEST1"",
""TEST2"",
""TEST3"",
""TEST4"",
""TEST5"",
""TEST6""
]
}
]";
var j = SomeNamespace.SomeRoot.FromJson(s);
var x = j.Select(e => {
var map = e.Valeurs.Select((v, i) => (v, i)).OrderBy(t => t.v).Select(t => t.i).ToArray();
return new SomeNamespace.SomeRoot
{
GroupBy = e.GroupBy,
Valeurs = map.Select(i => e.Valeurs[i]).ToArray(),
ProductUid = map.Select(i => e.ProductUid[i]).ToArray(),
};
}
);
//parsing classes
namespace SomeNamespace
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class SomeRoot
{
[JsonProperty("groupBy")]
public string GroupBy { get; set; }
[JsonProperty("valeurs")]
public string[] Valeurs { get; set; }
[JsonProperty("ProductUid")]
public string[] ProductUid { get; set; }
}
public partial class SomeRoot
{
public static SomeRoot[] FromJson(string json) => JsonConvert.DeserializeObject<SomeRoot[]>(json, SomeNamespace.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this SomeRoot[] self) => JsonConvert.SerializeObject(self, SomeNamespace.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}