Как транспонировать строки строки в столбцы, используя списки во вложенном foreach l oop C# - PullRequest
1 голос
/ 03 августа 2020

У меня есть строка, структурированная следующим образом:

RLLR
LRRL
RVVL
RRRR

// string was made like:
string s = "RLLR" + "\n" + "LRRL" + "\n" + "RVVL" + "\n" + "RRRR"; 

Что я хочу сделать с этой таблицей, так это транспонировать строки в столбцы, поэтому она будет выглядеть так:

RLRR
LRVR
LRVR
RLLR

Что я сделал до сих пор, так это то, что я преобразовал строку в массив, чтобы я мог пройти через него l oop следующим образом:

List<string> line_value = new List<string>();//list for one line of array
List<string> single_value = new List<string>();//list for individual characters for those lines

string s = "RLLR" + "\n" + "LRRL" + "\n" + "RVVL" + "\n" + "RRRR"; 
string[] strarray = new string[]{""};
strarray = s.Split("\n");
int z = 0;
foreach(string line in strarray)
{
     line_value.Add(line);//adds single line to list

      foreach(char letter in line_value[z])
      {
        Console.WriteLine(letter.ToString());
        single_value.Add(letter.ToString());
      }
   z++;
}  

Делая это таким образом, я могу распечатать строку, например Итак, где все горизонтально:

R
L
L
R
L
R
R
.
.
.
R

Однако я все еще не понимаю, как установить sh строку, чтобы она была транспонирована следующим образом:

RLRR
LRVR
LRVR
RLLR

Как мне переставить строку, чтобы она превратила строки в столбцы?

Ответы [ 2 ]

2 голосов
/ 03 августа 2020

Самый простой способ сделать это - сделать это без foreach l oop и использовать вместо l oop, злоупотребляя тем фактом, что вы можете просто поменять местами индексы столбца и строки.

using System.Text;

static string TransposeRowsToColumns(string rowString)
{
    string[] rows = rowString.Split("\n");

    StringBuilder columnBuilder = new StringBuilder();

    for (int columnIndex = 0; columnIndex < rows[0].Length; columnIndex++)
    {
        for (int rowIndex = 0; rowIndex < rows.Length; rowIndex++)
        {
            columnBuilder.Append(rows[rowIndex][columnIndex]);
        }
        
        columnBuilder.Append("\n");
    }

    return columnBuilder.ToString();
}

Обратите внимание, что приведенный выше код основан на том факте, что количество столбцов одинаково.

Если вы хотите сделать это с помощью foreach l oop со списками, вы можно сделать это так:

static string TransposeRowsToColumnsList(string rowString)
{
    string[] rows = rowString.Split("\n");
    List<List<string>> grid = new List<List<string>>();

    int columnIndex = 0;

    foreach (string row in rows)
    {
        grid.Add(new List<string>());

        foreach (string column in rows.Select(r => string.Concat(r.Skip(columnIndex).Take(1))))
        {
            grid[columnIndex].Add(column);
        }

        columnIndex++;
    }

    return string.Join("\n", grid.Select(r => string.Concat(r.Select(c => c))));
}

Использование:

string s = "RLLR" + "\n" + "LRRL" + "\n" + "RVVL" + "\n" + "RRRR"; 

Console.WriteLine(TransposeRowsToColumns(s));
Console.WriteLine(TransposeRowsToColumnsList(s));

Edit

Для изменения ввода по существу разделите столбцы по пробелу вместо того, чтобы предполагать, что они являются одним символом, мы можем изменить второй метод, чтобы он выглядел так:

static string TransposeRowsToColumnsList(string inputString, string columnSplitBy = "", string rowSplitBy = "\n")
{
    IEnumerable<IEnumerable<string>> inputGrid = inputString.Split(rowSplitBy).Select(r =>
    {
        return columnSplitBy == "" ? r.Select(c => new string(c, 1)).ToArray() : r.Split(columnSplitBy);
    });
    
    List<List<string>> outputGrid = new List<List<string>>();

    int columnIndex = 0;

    foreach (IEnumerable<string> row in inputGrid)
    {
        outputGrid.Add(new List<string>());

        foreach (string column in inputGrid.Select(r => string.Concat(r.Skip(columnIndex).Take(1))))
        {
            outputGrid[columnIndex].Add(column);
        }

        columnIndex++;
    }

    return string.Join(rowSplitBy, outputGrid.Select(r => string.Concat(string.Join(columnSplitBy, r.Select(c => c)))));
}

Хотя это очень быстро становится беспорядочным. Для более масштабируемого решения мы можем создать методы расширения, чтобы отделить каждый этап алгоритма и выдать желаемый результат.

Сначала мы определяем интерфейс, который может преобразовывать строку в желаемый тип с реализацией преобразования десятичные дроби:

public interface IStringConverter<T>
{
    T ConvertFromString(string input);
}

public class DecimalConverter : IStringConverter<decimal>
{
    public decimal ConvertFromString(string input)
    {
        return decimal.Parse(input);
    }
}

Затем мы можем определить все методы расширения, которые нам понадобятся, чтобы транспонировать сетку так, как мы хотим:

public static class CustomExtensions
{
    public static IEnumerable<string> ForceSplit(this string input, string pattern)
    {
        return pattern != string.Empty ? input.Split(pattern) : input.Select(x => x.ToString());
    }
    
    public static IEnumerable<IEnumerable<string>> ConvertToGrid(this string input, string columnSplit = "", string rowSplit = "\n")
    {
        return input.Split(rowSplit).Select(r => r.ForceSplit(columnSplit));
    }
    
    public static IEnumerable<IEnumerable<T>> ConvertToGrid<T>(this string input, IStringConverter<T> converter, string columnSplit = "", string rowSplit = "\n")
    {
        return input.Split(rowSplit).Select(r => r.ForceSplit(columnSplit).Select(converter.ConvertFromString));
    }

    public static IEnumerable<IEnumerable<T>> PivotGrid<T>(this IEnumerable<IEnumerable<T>> input)
    {
        return input
            .SelectMany(r => r.Select((c, index) => new {column = c, index}))
            .GroupBy(i => i.index, i => i.column)
            .Select(g => g.ToList());
    }

    public static string ConvertToString<T>(this IEnumerable<IEnumerable<T>> input, string columnSplit = "", string rowSplit = "\n")
    {
        return string.Join(rowSplit, input.Select(r => string.Join(columnSplit, r)));
    }
}

Примечания:

  • Теперь мы конвертируем каждый элемент в ячейку желаемого типа через ConvertToGrid
  • Мы можем перемещать сетку из строк в столбцы (спасибо за этот ответ )
  • Затем при желании мы можем преобразовать сетку обратно в строковый формат

Использование

string letters = "RLLR" + "\n" + "LRRL" + "\n" + "RVVL" + "\n" + "RRRR"; 
string numbers = "25.0 45.7 23" + "\n" + "12.4 67.4 0.0" + "\n" + "0.00 0.00 0.00" + "\n" + "67.8 98.4 0.00"; 

string transposedLetters = TransposeRowsToColumnsList(letters);
string transposedNumbers = TransposeRowsToColumnsList(numbers, " ");

string pivotedLetters = letters
    .ConvertToGrid()
    .PivotGrid()
    .ConvertToString();

string pivotedNumbers = numbers
    .ConvertToGrid(new DecimalConverter(), " ")
    .PivotGrid()
    .ConvertToString(" ");

Я лично нахожу способ расширения подход более удобен в обслуживании и более расширяемый, но исходный метод легче вызвать.

2 голосов
/ 03 августа 2020

Попробуйте следующее: используйте один l oop для буквенного индекса и другой, вложенный в l oop слова:

        string[] strarray = { "AAA", "BBB", "CCC" };
        for (int i = 0; i < strarray.Length; i++)
        {
            for (int j = 0; j < strarray.Length; j++)
            {
                Console.Write(strarray[j][i]);
            }
            Console.WriteLine();
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...