Ehsan Davoudi
Ehsan Davoudi

Reputation: 81

Sort string array in special format

It need to sort a string array like this to a special format. Our Array is:

input1 = new string[12]{"Active1","12","mm","Active2","17","mm","Width","25","mil","Height","20","mil"}  

and our desired sort list is:

sort = new string[6]{"Serial","Width","Height","Active1","Active2","Time"}  

My valid format for output is this:

Output = [{Serial,null,null},{Width,25,mil},{Height,20,mil},{Active1,12,mm},{Active2,17,mm},{Time,null,null}]

It is necessary to set null value for data that don't exist in Input Array.

I'm using this code for my purpose:

var Output = (from i in Enumerable.Range(0, input.Length / 3)
                       let index = Array.IndexOf(sort, input[i * 3])
                       where index >= 0
                       select ne3w string[] { input[i * 3], input[i * 3 + 1] , input[i * 3 + 2]})
                       .OrderBy(a => Array.IndexOf(sort, a[0])).ToArray();

but it doesn't show the values that don't exist in input Array.

Upvotes: 2

Views: 106

Answers (5)

Dejan Ciev
Dejan Ciev

Reputation: 142

I think this code is good for your problem.

 static List<string[]> SortedList(string[] input)
    {
        var sort = new string[6] { "Serial", "Width", "Height", "Active1", "Active2", "Time" };
        List<string[]> output = new List<string[]>();
        for (int i = 0; i < sort.Length; i++)
        {
            var findIndex = input.ToList().IndexOf(sort[i]);
            if (findIndex != -1)
                output.Add(new string[3]
                    {
                        input[findIndex],
                        input[findIndex + 1],
                        input[findIndex + 2]
                    });
            else
                output.Add(new string[3]
                {
                    sort[i],
                    null,
                    null
                });
        }
        return output;
    }

And now you call that method:

 var input = new string[12] { "Active1", "12", "mm", "Active2", "17", "mm", "Width", "25", "mil", "Height", "20", "mil" };
 var output = SortedList(input);

Upvotes: 1

Arithmomaniac
Arithmomaniac

Reputation: 4794

Building on Nitesh, but removing the need to scan input repeatedly by using a dictionary

using System.Linq; //at top of file

private static string[][] TransformInput(string[] input)
{
    var sortOrder = new[] { "Serial", "Width", "Height", "Active1", "Active2", "Time" };

    //dictionary pointing words to position in input
    var inputDict = Enumerable.Range(0, input.Length/3)
            .Select(i => i*3).ToDictionary(i => input[i]);
    //Try to read position from dictionary; return nulls if fail
    return sortOrder.Select(x => {
            int i;
            return (inputDict.TryGetValue(x, out i))
                ? new[]{x, input[i+1], input[i+2]}
                : new[]{x, null, null};
        }).ToArray();
}

Upvotes: 1

Enigmativity
Enigmativity

Reputation: 117064

Given the two sets of input data:

var input1 = new string[12]
{
    "Active1","12","mm",
    "Active2","17","mm",
    "Width","25","mil",
    "Height","20","mil"
};

var sort = new string[6]
{
    "Serial","Width","Height","Active1","Active2","Time"
};

This worked for me:

var lookup =
    input1
        .Select((x, n) => new { x, n })
        .ToLookup(xn => xn.n / 3)
        .ToLookup(
            z => z.ElementAt(0).x,
            z => z.Skip(1).Select(w => w.x));

var result =
    sort
        .Select(x =>
            new [] { x }
                .Concat(lookup[x].SelectMany(z => z))
                .Concat(new string[] { null, null })
                .Take(3)
                .ToArray())
        .ToArray();

I got this result:

result

Upvotes: 1

Nitesh Patel
Nitesh Patel

Reputation: 631

I would put this into a separate method:

private static IEnumerable<string[]> TransformInput(string[] input)
{
    return from key in new[] { "Serial", "Width", "Height", "Active1", "Active2", "Time" }
           let keyIndex = Array.IndexOf(input, key)
           let hasData = keyIndex > 1
           select new[]
           {
               key,
               hasData ? input[keyIndex + 1] : null,
               hasData ? input[keyIndex + 2] : null
           };
}

And then use it as follows:

var input1 = new string[12]   
{ "Active1", "12", "mm", "Active2", "17", "mm", "Width", "25", "mil", "Height", "20", "mil" };

var sorted = TransformInput(input1);

Upvotes: 4

Sergio Schirmer
Sergio Schirmer

Reputation: 301

You can do it with the method below:

    private string[][] Sort(string[] input)
    {

        List<string> inputList = new List<string> ();
        inputList = input.ToList<string> ();

        List<string[]> sortedList = new List<string[]> ();

        string[] sort = new string[]{"Serial", "Width", "Height", "Active1", "Active2", "Time"};

        foreach(string key in sort)
        {
            if (inputList.Contains<string> (key)) {
                int i = inputList.IndexOf (key);
                string[] t = new string[]{inputList[i],inputList[i+1],inputList[i+2]};
                sortedList.Add (t);
            }
            else
            {
                string[] t = new string[]{key,null, null};
                sortedList.Add (t);
            }
        }

        return sortedList.ToArray<string[]> ();
    }

Hope it help you out!

Upvotes: 1

Related Questions