使用C# 7.1/.Net Framework 4.8将有序的逗号分隔列表转换为具有有序元素编号的元组(如SQL SPLIT_STRING)

zpgglvta  于 2022-12-01  发布在  .NET
关注(0)|答案(5)|浏览(106)

我似乎找不到一个现成的答案,或者即使这个问题以前曾经被问过,但我希望有类似于SQL STRING_SPLIT函数的功能,其中逗号分隔列表中的每个项目都由其在字符串中的序号标识。
给定字符串“abc,xyz,def,tuv”,我想得到一个元组列表,如下所示:

<1, "abc">
<2, "xyz">
<3, "def">
<4, "tuv">

顺序是很重要的,我需要保持顺序,并且能够使用linq将它与另一个列表进一步连接,并且能够保持顺序。例如,如果第二个列表是〈“tuv”,“abc”〉,我希望连接的最终输出是:

<1, "abc">
<4, "tuv">

基本上,我希望用逗号分隔的字符串来确定最终结果的顺序,其中逗号分隔的字符串包含所有可能的字符串,它与一个字符串子集的无序列表连接,输出是一个有序元组列表,该列表只包含第二个列表中的元素,但顺序由开头的逗号分隔的字符串确定。
如果我能得到一个C#中的各种SQL STRING_SPLIT函数的等价物,我就可以自己解决所有这些问题,这些函数不仅进行拆分,而且在输出中还包括有序元素编号。但是我搜索了一下,除了将字符串拆分为单个元素,或者将它们拆分为元组(元组的两个元素都在字符串中)之外,我没有找到C#中的任何内容。而不是生成的整数以保持顺序。
这里,顺序对我来说很重要。所以,如果元素编号不容易实现,那么,一种内部连接两个列表并保证保留第一个列表的顺序,同时只返回第二个列表中的元素的方法将是受欢迎的。对我来说,棘手的部分是最后一部分:连接的结果需要一个特定的(不容易排序的)顺序。序数可以给我排序的依据,但是如果我可以保证输出与第一个输入的顺序相同,那也可以。

rqqzpn5f

rqqzpn5f1#

这应该可以在.NET框架上工作。

using System.Linq;
string str = "abc,xyz,def,tuv";
string str2 = "abc,tuv";

IEnumerable< PretendFileObject> secondList = str2.Split(',').Select(x=> new PretendFileObject() { FileName = x}); //

var tups = str.Split(',')
    .Select((x, i) => { return (i + 1, x); })
    .Join(secondList, //Join Second list ON 
    item => item.Item2 //This is the filename in the tuples 
    ,item2 => item2.FileName, // This is the filename property for a given object in the second list to join on
    (item,item2) => new {Index = item.Item1,FileName = item.Item2, Obj = item2})
    .OrderBy(JoinedObject=> JoinedObject.Index)
    .ToList();

foreach (var tup in tups)
{
    Console.WriteLine(tup.Obj.FileName);
}

public class PretendFileObject
{
    public string FileName { get; set; }
    public string Foo { get; set; }
}

原始回应如下
如果你想坚持使用SQL,这里是如何使用linq操作符的,Select方法有一个内置的索引参数,你可以使用它,你可以使用IntersectBy来执行一个简单的内部连接。

using System.Linq;
string str = "abc,xyz,def,tuv";
string str2 = "abc,tuv";
var secondList = str2.Split(',');

var tups = str.Split(',')
    .Select((x, i) => { return (i + 1, x); })
    .IntersectBy(secondList, s=>s.Item2) //Filter down to only the strings found in both.
    .ToList();

foreach(var tup in tups)
{
    Console.WriteLine(tup);
}
y0u0uwnf

y0u0uwnf2#

这将得到元组列表

var input = "abc,xyz,def,tuv";
string[] items = input.Split(',');
var tuples = new List<(int, string)>();
for (int i = 0; i < items.Length)
{
    tuples.Add(((i + 1), items[i]));
}

如果你想添加"tuv""abc"的列表并保留1,你可能想“左连接”。2但是我不确定你如何使用LINQ,因为你首先需要迭代元组的原始列表并分配相同的int。3然后连接。4或者,你可以先连接,然后分配int,但是技术上,顺序是不保证的。5但是,如果先赋值int,最后可以按它排序。
我对 “有点困惑,我可以使用linq” 将列表与另一个列表进一步连接。连接通常意味着聚合结果。但在您的情况下,似乎您需要的是细分,而不是连接的数据。

  • “我想从第二个列表中删除不在第一个列表中的任何项,然后我需要按第一个列表的顺序遍历第二个列表”*
var input2 = "xxx,xyz,yyy,tuv,";
string[] items2 = input2.Split(',');

IEnumerable<(int, string)> finalTupleOutput = 
    tuples.Join(items2, t => t.Item2, i2 => i2, (t, i2) => (t.Item1, i2)).OrderBy(tpl => tpl.Item1);

这将为您提供所需的内容-将L2中的项目与L1中的顺序相匹配

gijlo24d

gijlo24d3#

虽然不能100%确定您的目标,但可以尝试:

string[] vals = new[] { "abc", "xyz", "dev", "tuv"};

string[] results = new string[vals.Length];

int index = 0;

for (int i = 0; i < vals.Length; i++)
{
    results[i] = $"<{++index},\"{vals[i]}\">";
}

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

这将产生:

<1,"abc">
<2,"xyz">
<3,"dev">
<4,"tuv">
oxosxuxt

oxosxuxt4#

使用LINQ

string inputString = "abc,xyz,def,tuv";
var output = inputString.Split(',')
.Select((item, index) => { return (index + 1, item); });

现在您可以根据需要使用output列表。

deyfvvtc

deyfvvtc5#

给定示例
例如,如果第二个列表是〈“tuv”,“abc”〉,我希望连接的最终输出是:
〈1,“abc”〉〈4,“tuv”〉
我想这可能是关闭?

List<string> temp = new List<string>() { "abc", "def", "xyz", "tuv" };
List<string> temp2 = new List<string>() { "dbc", "ace", "zyw", "tke", "abc", "xyz" };
var intersect = temp.Intersect(temp2).Select((list, idx) => (idx+1, list));

这将产生一个交集结果,该结果具有列表1中的元素,这些元素也在列表2中,在本例中,交集结果为:

<1, "abc">
<2, "xyz">

如果您需要两个列表中的 all 元素,请将Intersect切换为Union

相关问题