Home > Software engineering >  How to insert a text in List using linq
How to insert a text in List using linq

Time:01-11

I am very new to linq programining in c# and I have below text file and read the file and stored in List

IP/ Text file DC List:

North: &North
**arr prod_test**
Dcname BN14

south: &south
**arr prod_test**
Dcname BN1

East: &East
**arr ff_test**
DcName RD1

NorthEast: &NorthEast
**arr mc_test**
DcName RR

WestEast: &NorthEast
**arr mc_test**
DcName RR

O/p file:

DC List:

North: &North
**arr prod_test**
Dcname BN14

south: &south
**arr prod_test**
Dcname BN1

East: &East
**arr ff_test**
DcName RD1

/// here I need to add the new text my doubt is how to find the  insert position and how to add the content using linq query 
West: &West
**arr ff_test**
DcName RD1

NorthEast: &NorthEast
**arr mc_test**
DcName RR

WestEast: &NorthEast
**arr mc_test**
DcName RR

I need to search for arr_ff_test and need to insert the next content before East: &East, Please help me in this using linq.

List<string> lines = File.ReadAllLines(buildOutFile).ToList();
index = lines.FindIndex(element => element.Contains("arr ff_test"));
temp = String.Format($"West: &West\n    **arr ff_test**\nDcName RD1);
lines.Insert(index-1, temp);

I want to change above three lines to linq

CodePudding user response:

Supposing that the position of the entries counts somehow, I understand that you need to insert the block referring to West after the East part. That is to say before the NorthEast one, correct? In that case it seems easier that you look for NorthEast instead and insert preceding than to look for East and insert after.

in that case the code becomes:

private List<string> Merge2(string buildOutFile)
{
var lines = File.ReadAllLines(buildOutFile).ToArray();
var textToInsert = new List<string>()
{
    "West: &West",
    "**arr ff_test**",
    "DcName RD1"
}.ToArray();
var oneLineSource = string.Join(Environment.NewLine, lines);
var oneLineinsertion = string.Join(Environment.NewLine, textToInsert);
var separator = "NorthEast: &NorthEast";
var twoParts = oneLineSource.Split(separator);
string onelinerOutput = twoParts[0]   oneLineinsertion   twoParts[1];
return onelinerOutput.Split().ToList();
}

If you want to use linq at every cost:

private List<string> Merge(string buildOutFile)
{
    var lines = File.ReadAllLines(buildOutFile);
    var separator = "NorthEast: &NorthEast";
    var textToInsert = $"{separator}{Environment.NewLine}West: &West{Environment.NewLine}**arr ff_test**{Environment.NewLine}DcName RD1{ Environment.NewLine}"; 
    return lines.Select(line=>line.Contains(separator)?textToInsert:line).ToList();                    
}

In case your additional text is not hardcoded you can simply put other placeholders in the separator interpolated string to get it customizable.

CodePudding user response:

As I mentioned in the comments, you need to use streams here. You should not read the lines in an array, then use LINQ to do what you want, since this action of iterating a collection and modifying it is bad design.

Here is a sample code that I tested. I added comments to explain my code as well.

public void ReadText()
{
    // Stream for the existing file "sample.txt"
    using (StreamReader input = new StreamReader(new FileStream("sample.txt", FileMode.Open)))
    {
        // Stream for output file that is to be created or overwritten
        using (StreamWriter output = new StreamWriter(new FileStream("output.txt", FileMode.OpenOrCreate)))
        {
            // We need to look ahead two lines at a time
            string second_line, first_line;
            first_line = input.ReadLine();

            // This loop goes on for every line in the input file
            while ((second_line = input.ReadLine()) != null)
            {
                if (second_line.Contains("arr ff_test")) // This is the line where the insertions are to be made
                {
                    // Now insert the extra lines you want in your output file
                    output.WriteLine("West: &West");
                    output.WriteLine("**arr ff_test**");
                    output.WriteLine("DcName RD1");
                    output.WriteLine(); // Make an empty line
                }
                output.WriteLine(first_line); // write the same line in output as it is
                first_line = second_line; // the first line is moved foreward
            }
            output.Write(first_line); // The last line is yet to be written

            // Close both the files
            output.Close();
        }
        input.Close();
    }
}

The trick here is to look ahead two lines at a time. I tested it with your given input and output files and seems to work just fine.

CodePudding user response:

Assuming the input file is uniformly composed of blocks of 3 lines each followed by an empty line, you only need the line index of that 'arr ff_test' entry and calculate the next follwing multiple of 4. There insert your additional lines. And you're done.
The 'Q' in 'LinQ' indicates it's most powerful for querying lists. Wouldn't recommend it for insertion of text. List<string> is the tool with everything necessary already built-in.

    var lines = File.ReadAllLines(inputFilePath).ToList();
    var matchPos = lines.IndexOf("**arr ff_test**");
    if (matchPos > -1)  {
        // get next multiple of 4 as insertion index ...
        var insertPos = ((matchPos / 4)   1) * 4; 
        lines.InsertRange(insertPos, new[] {
            "West: &West", "**arr ff_test**", "DcName RD1", ""});
        File.WriteAllLines(outputFilePath, lines.ToArray());
    }
  • Related