tags:

views:

2423

answers:

7

How do I append the previous item in array to the next item in the array for unknown number of items?

Here is what I'm trying to do. I have a string containing an LDAP path such as "OU=3,OU=2,OU=1,DC=Internal,DC=Net", I want to create each container in the above LDAP path so from the above string I need to create an array with the contents below so I can create each container. The first array item needs creating before I can create the second etc.

"OU=1,DC=Internal,DC=Net"

"OU=2,OU=1,DC=Internal,DC=Net"

"OU=3,OU=2,OU=1,DC=Internal,DC=Net"

My string example is just an example so the path may be longer or shorter and could contain 1 array item or 10+ I just don't know so I won't know how many array items there are I need to loop through them all so I have all the paths in the array.

Another example:

From "OU=Test4,OU=Number3,OU=Item2,OU=1,DC=Internal,DC=Net" I need:

"OU=1,DC=Internal,DC=Net" "OU=Item2,OU=1,DC=Internal,DC=Net" "OU=Number3,OU=Item2,OU=1,DC=Internal,DC=Net" "OU=Test4,OU=Number3,OU=Item2,OU=1,DC=Internal,DC=Net"

Thanks for the help with this.

J

A: 

If the string will always end with ",DC=Internal,DC=Net", the following solution should get you going.

static string[] Split(string path)
{
    const string postfix = ",DC=Internal,DC=Net";
    string shortPath = path.Substring(0, path.Length - postfix.Length);
    return shortPath.Split(',').Select(x => x + postfix).ToArray();
}

Edit 2.0 solution

static string[] Split(string path)
{
    const string postfix = ",DC=Internal,DC=Net";
    string shortPath = path.Substring(0, path.Length - postfix.Length);
    string[] items = shortPath.Split(',');
    List<string> final = new List<string>();
    foreach ( string item in items ) { 
      final.Add(item + postfix);
    }
    return final.ToArray();

}
JaredPar
Compiler Error Message: CS1061: 'System.Array' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)
balexandre
Hi, Thanks for the help, I'm getting errors on the last line with (x => x + postfix) not being recognized. I'm using .Net 2.0. Was this for 3.5?
Yes, this is a 3.5 construct. I'll add a 2.0 answer.
JaredPar
@balexandre, sorry, this is a C# 3.5 solution. I added a 2.0 solution.
JaredPar
+4  A: 

I'm not sure I understood correctly. Do you need something like this:

string input = "OU=3,OU=2,OU=1,DC=Internal,DC=Net";
string[] split = input.Split(',');

string path = "";
for (int i=split.Length-1; i>=0; i--)
{
    path = ((path == "") ? split[i] : split[i] + "," + path);
    if (path.StartsWith("OU"))
     DoSomething(path);
}

This will call DoSomething() three times, for the following strings:

  • OU=1,DC=Internal,DC=Net
  • OU=2,OU=1,DC=Internal,DC=Net
  • OU=3,OU=2,OU=1,DC=Internal,DC=Net
M4N
A: 

Here's come code example (assuming you have .NET 3.5):

// First we need to split up the initial string
string[] items = initialString.Split("'");

// Then we filter it so that we have a list of OU and non-OU items
string[] ouItems = items.Where(s=>s.StartsWith("OU=")).ToArray();
string[] nonOuItems = items.Where(s=>!s.StartsWith("OU=")).ToArray();

List<string> mainList = new List<string>();

// Our main loop
for (int i = 0; i < ouItems.Length; i++)
{
    List<string> localList = new List<string>();

    // We loop through all the previous items including the current one
    for (int j = 0; j <= i; j++)
    {
        localList.Add(ouItems[i]);
    }
    // Then we add all of the non-OU items
    localList.AddRange(nonOuItems);

    // Then we build the string itself
    bool first = true;
    StringBuilder sb = new StringBuilder();
    foreach (string s in localList)
    {
        if (first) first = false;
        else sb.Append (","); // Separating the items with commas
        sb.Append(s);
    }
    mainList.Add(sb.ToString());
}

// Now we only have to convert it back to an array
string[] finalArray = mainList.ToArray();

Even if you don't have .NET 3.5 it should be pretty straightforward to port that back to .NET 2.0. Also, I haven't tested this so there may be bugs or typos in there. Also, this is definitely not the most effective way to do it but I think it is quite obvious and will probably work.

DrJokepu
A: 

This should give you an array in the right order, a bit longer since it's an actual console app:

using System;
using System.Text;

namespace Splitomatic
{
    public class Program
    {
        /// <summary>
        /// Sample Input: 
        ///    arg[0]: OU=Test4,OU=Number3,OU=Item2,OU=1
        ///    arg[1]: DC=Internal,DC=Net
        /// </summary>
        /// <param name="args"></param>
        public static void Main(string[] args)
        {
            StringBuilder builder;
            string[] containers;
            string[] parts;

            if (args.Length != 2)
            {
                Console.WriteLine("Usage: <exe> <containers> <append");
            }

            builder = new StringBuilder(args[1]);
            parts = args[0].Split(',');
            containers = new string[parts.Length];

            for (int i = parts.Length - 1; i >= 0; --i)
            {
                builder.Insert(0, ",");
                builder.Insert(0, parts[i]);
                containers[Math.Abs(i - parts.Length + 1)] = builder.ToString();
            }

            Console.WriteLine("Dumping containers[]:");
            for (int i = 0; i < containers.Length; ++i)
            {
                Console.WriteLine("containers[{0}]: {1}", i, containers[i]);
            }

            Console.WriteLine("Press enter to quit");
            Console.ReadLine();
        }
    }
}

Sample output:

Dumping containers[]:
containers[0]: OU=1,DC=Internal,DC=Net
containers[1]: OU=Item2,OU=1,DC=Internal,DC=Net
containers[2]: OU=Number3,OU=Item2,OU=1,DC=Internal,DC=Net
containers[3]: OU=Test4,OU=Number3,OU=Item2,OU=1,DC=Internal,DC=Net
Press enter to quit
Nicholas Piasecki
A: 

One method. This will create a string for each of the DCs as well.

string[] GetArray(string input)
{
    string[] vals = input.Split(',');

    List<string> entries = new List<string>();

    string s;
    for(int i=vals.Length - 1; i > 0; i--)
    {
        s = vals[i];

        if(i < vals.Length - 1)
           s += "," +  entries[(vals.Length - 2) - i];

        entries.Add(s);
    }

   return entries.ToArray();
}
BobbyShaftoe
A: 

My code is almost like Martin's but his code outputs a comma on the end of all the path object.

Here is the correct function:

static string[] SplitLDAPPath(string input)
{
    List<String> r = new List<string>();
    string[] split = input.Split(',');

    string path = "";
    for (int i = split.Length - 1; i >= 0; i--)
    {
        path = split[i] + "," + path;
        if (path.StartsWith("OU"))
            r.Add(path.Substring(0, path.Length-1));
    }
    return r.ToArray();
}

using:

    String s = "OU=Test4,OU=Number3,OU=Item2,OU=1,DC=Internal,DC=Net";
    String[] r = SplitLDAPPath(s);

    foreach (String ss in r)
        lt.Text += ss + "<br/>";

outputs:

OU=1,DC=Internal,DC=Net
OU=Item2,OU=1,DC=Internal,DC=Net
OU=Number3,OU=Item2,OU=1,DC=Internal,DC=Net
OU=Test4,OU=Number3,OU=Item2,OU=1,DC=Internal,DC=Net
balexandre
I had already fixed the code (removed the trailing comma).
M4N
Nice, I will not delete this just to give the entire function, but I dont expect any upvote... I just gave you mine upvote :)
balexandre
Thanks. BTW: you named the method SplitLDAPPath(), but in the example you are calling Split()
M4N
A: 

If I understand your question correctly:

  • Split the string on a semicolon, producing N items
  • The result of the method should be a number of strings
  • The first string should be the last item, after splitting by semicolons
  • The next item should be whatever came before the last item, a semicolon, and the last item
  • The next item should be whatever came before the previous item, a semicolon, and then the previous item

Then the implementation should be fairly straightforward:

public static IEnumerable<String> LastToFirstOrSomething(String s)
{
    String[] parts = s.Split(';');
    String result = String.Empty;
    for (Int32 index = parts.Length - 1; index >= 0; index--)
    {
        if (result.Length > 0)
            result = ";" + result;
        result = parts[index] + result;
        yield return result;
    }
}

Of course, this could possibly be improved, performance-wise, through the use of a StringBuilder.

Now, having said all that, I know that your question doesn't match 100% my answer, because you haven't said why you're not providing the first X elements, you skip those. Why is that?

You need to provide more information for a better answer.

Lasse V. Karlsen