কীভাবে: কনসোল অ্যাপে সারণি আঁকার সেরা উপায় (সি #)


104

আমি একটি আকর্ষণীয় প্রশ্ন আছে। কল্পনা করুন আমার খুব দ্রুত ব্যবধানে প্রচুর ডেটা পরিবর্তন হচ্ছে। আমি কনসোল অ্যাপ্লিকেশনটিতে টেবিল হিসাবে সেই তথ্যটি প্রদর্শন করতে চাই। f.ex:

-------------------------------------------------------------------------
|    Column 1     |    Column 2     |    Column 3     |    Column 4     |
-------------------------------------------------------------------------
|                 |                 |                 |                 |
|                 |                 |                 |                 |
|                 |                 |                 |                 |
-------------------------------------------------------------------------

কীভাবে জিনিসগুলি দ্রুত রাখবেন এবং কলামের প্রশস্ততা কীভাবে ঠিক করবেন? আমি জাভাতে এটি কীভাবে করব তা আমি জানি তবে এটি সি # তে কীভাবে হয়েছে তা আমি জানি না।


6
আপনি যদি নিজের জাভা সমাধানটি সরবরাহ করেন তবে কেউ সি # তে অনুবাদ করতে আপনাকে সহায়তা করতে পারে? দৈর্ঘ্য / প্যাডলফ্ট / প্যাডরাইট / ... সহ স্ট্রিং ক্লাসটি একবার দেখুন
স্কোরগ্রাফিক

উত্তর:


66

আপনি নিম্নলিখিত মত কিছু করতে পারে:

static int tableWidth = 73;

static void Main(string[] args)
{
    Console.Clear();
    PrintLine();
    PrintRow("Column 1", "Column 2", "Column 3", "Column 4");
    PrintLine();
    PrintRow("", "", "", "");
    PrintRow("", "", "", "");
    PrintLine();
    Console.ReadLine();
}

static void PrintLine()
{
    Console.WriteLine(new string('-', tableWidth));
}

static void PrintRow(params string[] columns)
{
    int width = (tableWidth - columns.Length) / columns.Length;
    string row = "|";

    foreach (string column in columns)
    {
        row += AlignCentre(column, width) + "|";
    }

    Console.WriteLine(row);
}

static string AlignCentre(string text, int width)
{
    text = text.Length > width ? text.Substring(0, width - 3) + "..." : text;

    if (string.IsNullOrEmpty(text))
    {
        return new string(' ', width);
    }
    else
    {
        return text.PadRight(width - (width - text.Length) / 2).PadLeft(width);
    }
}

137

প্রান্তিককরণের মানগুলির সাথে স্ট্রিং.ফর্ম্যাট ব্যবহার করুন ।

উদাহরণ স্বরূপ:

String.Format("|{0,5}|{1,5}|{2,5}|{3,5}|", arg0, arg1, arg2, arg3);

একটি ফর্ম্যাট সারি তৈরি করতে।


যে চারবার একই মান মুদ্রণ করবে না?
ব্রায়ান রাসমুসেন

4
হ্যাঁ, আপনার ঠিক করা উচিত: স্ট্রিং.ফর্ম্যাট ("| {0,10} | {1,10} | {2,10} | {3,10} |", আরজি 0, আরজি 1, আরজি 2, আরজি 3);
Lukas Šalkauskas

4
আপনার যদি টেবিল প্রান্ত এবং কোণগুলির প্রয়োজন না হয় তবে এটি ভালভাবে কাজ করে। আপনার ব্যবধানে আপনাকে সহায়তা করতে প্যাডরাইট (এক্স) বা প্যাডলাইফ্ট (এক্স) ব্যবহার করতে ভুলবেন না। আমার যা প্রয়োজন, তার জন্য আমার পড়ার সহজ কিছু দরকার ছিল, এবং | গুলি সরিয়ে দেওয়ার পরে এটি কৌশলটি করেছিল।
কোকো ওয়ারে

4
-বাম-সারিবদ্ধ সামগ্রীগুলির জন্য ব্যবহার করুন , উদাহরণস্বরূপ:{0,-5}
মেহেদী দেহঘানি

মানগুলি সারিবদ্ধ করার জন্য আমি কীভাবে এটি ব্যবহার করব যেখানে একটি যুক্তি হয় সারিবদ্ধভাবে উপলব্ধ জায়গার প্রান্তকে উপচে ফেলে বা একটি নতুন রেখার অক্ষর ধারণ করে?
ব্যবহারকারী9811991

35

সম্পাদনা: @superlogical ধন্যবাদ, আপনি এখন এটি এবং নিম্নলিখিত কোড উন্নত করতে পারেন GitHub !


আমি এখানে কিছু ধারণার উপর ভিত্তি করে এই ক্লাসটি লিখেছি। কলামগুলির প্রস্থটি সর্বোত্তম, এটি এটি এই সাধারণ API এর সাহায্যে অবজেক্ট অ্যারেগুলি পরিচালনা করতে পারে:

static void Main(string[] args)
{
  IEnumerable<Tuple<int, string, string>> authors =
    new[]
    {
      Tuple.Create(1, "Isaac", "Asimov"),
      Tuple.Create(2, "Robert", "Heinlein"),
      Tuple.Create(3, "Frank", "Herbert"),
      Tuple.Create(4, "Aldous", "Huxley"),
    };

  Console.WriteLine(authors.ToStringTable(
    new[] {"Id", "First Name", "Surname"},
    a => a.Item1, a => a.Item2, a => a.Item3));

  /* Result:        
  | Id | First Name | Surname  |
  |----------------------------|
  | 1  | Isaac      | Asimov   |
  | 2  | Robert     | Heinlein |
  | 3  | Frank      | Herbert  |
  | 4  | Aldous     | Huxley   |
  */
}

এখানে ক্লাস:

public static class TableParser
{
  public static string ToStringTable<T>(
    this IEnumerable<T> values,
    string[] columnHeaders,
    params Func<T, object>[] valueSelectors)
  {
    return ToStringTable(values.ToArray(), columnHeaders, valueSelectors);
  }

  public static string ToStringTable<T>(
    this T[] values,
    string[] columnHeaders,
    params Func<T, object>[] valueSelectors)
  {
    Debug.Assert(columnHeaders.Length == valueSelectors.Length);

    var arrValues = new string[values.Length + 1, valueSelectors.Length];

    // Fill headers
    for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
    {
      arrValues[0, colIndex] = columnHeaders[colIndex];
    }

    // Fill table rows
    for (int rowIndex = 1; rowIndex < arrValues.GetLength(0); rowIndex++)
    {
      for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
      {
        arrValues[rowIndex, colIndex] = valueSelectors[colIndex]
          .Invoke(values[rowIndex - 1]).ToString();
      }
    }

    return ToStringTable(arrValues);
  }

  public static string ToStringTable(this string[,] arrValues)
  {
    int[] maxColumnsWidth = GetMaxColumnsWidth(arrValues);
    var headerSpliter = new string('-', maxColumnsWidth.Sum(i => i + 3) - 1);

    var sb = new StringBuilder();
    for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++)
    {
      for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
      {
        // Print cell
        string cell = arrValues[rowIndex, colIndex];
        cell = cell.PadRight(maxColumnsWidth[colIndex]);
        sb.Append(" | ");
        sb.Append(cell);
      }

      // Print end of line
      sb.Append(" | ");
      sb.AppendLine();

      // Print splitter
      if (rowIndex == 0)
      {
        sb.AppendFormat(" |{0}| ", headerSpliter);
        sb.AppendLine();
      }
    }

    return sb.ToString();
  }

  private static int[] GetMaxColumnsWidth(string[,] arrValues)
  {
    var maxColumnsWidth = new int[arrValues.GetLength(1)];
    for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
    {
      for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++)
      {
        int newLength = arrValues[rowIndex, colIndex].Length;
        int oldLength = maxColumnsWidth[colIndex];

        if (newLength > oldLength)
        {
          maxColumnsWidth[colIndex] = newLength;
        }
      }
    }

    return maxColumnsWidth;
  }
}

সম্পাদনা করুন: আমি একটি সামান্য উন্নতি যুক্ত করেছি - আপনি যদি কলামের শিরোনামগুলি সম্পত্তির নাম হতে চান তবে নিম্নলিখিত পদ্ধতিটি যুক্ত করুন TableParser(নোট করুন যে এটি প্রতিবিম্বের কারণে কিছুটা ধীর হবে):

public static string ToStringTable<T>(
    this IEnumerable<T> values,
    params Expression<Func<T, object>>[] valueSelectors)
{
  var headers = valueSelectors.Select(func => GetProperty(func).Name).ToArray();
  var selectors = valueSelectors.Select(exp => exp.Compile()).ToArray();
  return ToStringTable(values, headers, selectors);
}

private static PropertyInfo GetProperty<T>(Expression<Func<T, object>> expresstion)
{
  if (expresstion.Body is UnaryExpression)
  {
    if ((expresstion.Body as UnaryExpression).Operand is MemberExpression)
    {
      return ((expresstion.Body as UnaryExpression).Operand as MemberExpression).Member as PropertyInfo;
    }
  }

  if ((expresstion.Body is MemberExpression))
  {
    return (expresstion.Body as MemberExpression).Member as PropertyInfo;
  }
  return null;
}

গেটপোপার্টি পদ্ধতিটি কোথায়?
সুপারলজিকাল

4
@ সুপারলজিকাল, এটি উত্তরের নীচে যুক্ত করা হয়েছে। দেখার জন্য আপনাকে ধন্যবাদ।
হুবেজা

4
আমি এখানে অন্যান্য উত্তরগুলির তুলনায় স্ব-অন্তর্ভুক্ত এক্সটেনশন পদ্ধতি শৈলী পছন্দ করি। ধন্যবাদ!
জেমস হগ

4
সন্ত্রস্ত আমি এটা ব্যবহার করা হয় এবং এটা পুরোপুরি কাজ করে, শুধু এই সম্পাদিত arrValues[rowIndex, colIndex] = valueSelectors[colIndex].Invoke(values[rowIndex - 1]).ToString();করার জন্য var val = valueSelectors[colIndex].Invoke(values[rowIndex - 1]); arrValues[rowIndex, colIndex] = val == null ? "null" : val.ToString();এই ভাবে এটা নাল দেখায়।
এইচএইচএইচ

আপনি অ-ইউনিকোড অক্ষরগুলির সাথে কাজ শুরু না করা পর্যন্ত এটি দুর্দান্ত কাজ করে। তারপরে প্রস্থটি সমস্ত গন্ডগোল করে।
থম

30

বেশ কয়েকটি ওপেন-সোর্স লাইব্রেরি রয়েছে যা সাধারণ (এগুলির উত্তরগুলিতে কোড নমুনার মতো) থেকে আরও উন্নততর অবধি কনসোল টেবিল বিন্যাসকে মঞ্জুরি দেয়।

কনসোল টেবিল

নিউগেটের পরিসংখ্যান দ্বারা বিচার করা, সারণী বিন্যাসের জন্য সর্বাধিক জনপ্রিয় লাইব্রেরি কনসোলটেবল । টেবিলগুলি এভাবে তৈরি করা হয় (রিডমে ফাইল থেকে):

var table = new ConsoleTable("one", "two", "three");
table.AddRow(1, 2, 3)
     .AddRow("this line should be longer", "yes it is", "oh");

পূর্বনির্ধারিত স্টাইলগুলির মধ্যে একটি ব্যবহার করে টেবিলগুলি ফর্ম্যাট করা যায়। এটি দেখতে এরকম দেখাবে:

--------------------------------------------------
| one                        | two       | three |
--------------------------------------------------
| 1                          | 2         | 3     |
--------------------------------------------------
| this line should be longer | yes it is | oh    |
--------------------------------------------------

এই গ্রন্থাগারটি বিন্যাস ছাড়াই একক-লাইন কক্ষ প্রত্যাশা করে।

আরও লাইন শৈলীর মতো সামান্য বর্ধিত বৈশিষ্ট্য সেট সহ কনসোলটেবলের উপর ভিত্তি করে বেশ কয়েকটি গ্রন্থাগার রয়েছে।

সিসকনসোলফর্ম্যাট

আপনার যদি আরও জটিল ফর্ম্যাটিংয়ের প্রয়োজন হয় তবে আপনি সিসকনসোলফর্ম্যাট ব্যবহার করতে পারেন † প্রক্রিয়া তালিকা থেকে তৈরি একটি সারণি এখানে (একটি নমুনা প্রকল্প থেকে):

new Grid { Stroke = StrokeHeader, StrokeColor = DarkGray }
    .AddColumns(
        new Column { Width = GridLength.Auto },
        new Column { Width = GridLength.Auto, MaxWidth = 20 },
        new Column { Width = GridLength.Star(1) },
        new Column { Width = GridLength.Auto }
    )
    .AddChildren(
        new Cell { Stroke = StrokeHeader, Color = White }
            .AddChildren("Id"),
        new Cell { Stroke = StrokeHeader, Color = White }
            .AddChildren("Name"),
        new Cell { Stroke = StrokeHeader, Color = White }
            .AddChildren("Main Window Title"),
        new Cell { Stroke = StrokeHeader, Color = White }
            .AddChildren("Private Memory"),
        processes.Select(process => new[] {
            new Cell { Stroke = StrokeRight }
                .AddChildren(process.Id),
            new Cell { Stroke = StrokeRight, Color = Yellow, TextWrap = TextWrapping.NoWrap }
                .AddChildren(process.ProcessName),
            new Cell { Stroke = StrokeRight, Color = White, TextWrap = TextWrapping.NoWrap }
                .AddChildren(process.MainWindowTitle),
            new Cell { Stroke = LineThickness.None, Align = HorizontalAlignment.Right }
                .AddChildren(process.PrivateMemorySize64.ToString("n0")),
        })
    )

শেষ ফলাফলটি এর মতো দেখবে:

এটি যেকোন ধরণের টেবিল লাইনকে সমর্থন করে (বেশ কয়েকটি অন্তর্ভুক্ত এবং কাস্টমাইজযোগ্য), শব্দের মোড়ক, রঙ, কলাম কন্টেন্ট বা শতাংশের উপর ভিত্তি করে বেড়ে যাওয়া, পাঠ্য প্রান্তিককরণ ইত্যাদি multi

S সিসকনসোলফর্ম্যাটটি আমার দ্বারা বিকাশ করা হয়েছিল।


আমি জানি এটি বেশ পুরানো, তবে আমি কীভাবে একটি বহু লাইন ঘর তৈরি করতে পারি? আমি এটি কোথাও
পাইনি

4
@ মর্টা 1 এর উত্তর বা সিএস কনসোল ফর্ম্যাট লাইব্রেরিও পুরানো নয়। আপনি যদি সিসকনসোলফর্ম্যাট ব্যবহার করছেন তবে আপনি নিজেই লাইন ব্রেকগুলি সন্নিবেশ করতে পারেন (কোষের অভ্যন্তরে স্ট্রিংগুলিতে "\ n") এবং এটি সঠিকভাবে পরিচালনা করা হবে, বা পাঠাগারটি স্বয়ংক্রিয়ভাবে মোড়ানো হোক (এটি ডিফল্ট, তাই আপনি ঠিক করেন না TextWrap = TextWrapping.NoWrapউপরের উদাহরণে অসদৃশ যোগ করুন )।
আটারি

দ্রুত উত্তরের জন্য ধন্যবাদ, কনসোলটেবলের সাথে এটি করার কোনও উপায় আছে কি?
মর্তা 1

4
@ মর্টা 1 নং। আমি মনে করি না যে কোনও সাধারণ লাইব্রেরি এটি সমর্থন করে।
অথরি

4
মত @HarveyDarvey কিছু new Cell(text) { Color = text == "true" ? Green : Red }। যদি আপনার অনুরূপ ফর্ম্যাটিং বিধি সহ অনেকগুলি সারণী থাকে তবে আপনি সেই কোডটি কোনও ফাংশনে রাখতে পারেন, এটি সেল, সারি বা পুরো টেবিলের জন্য হোক।
আটারি

23
class ArrayPrinter
    {
    #region Declarations

    static bool isLeftAligned = false;
    const string cellLeftTop = "┌";
    const string cellRightTop = "┐";
    const string cellLeftBottom = "└";
    const string cellRightBottom = "┘";
    const string cellHorizontalJointTop = "┬";
    const string cellHorizontalJointbottom = "┴";
    const string cellVerticalJointLeft = "├";
    const string cellTJoint = "┼";
    const string cellVerticalJointRight = "┤";
    const string cellHorizontalLine = "─";
    const string cellVerticalLine = "│";

    #endregion

    #region Private Methods

    private static int GetMaxCellWidth(string[,] arrValues)
    {
        int maxWidth = 1;

        for (int i = 0; i < arrValues.GetLength(0); i++)
        {
            for (int j = 0; j < arrValues.GetLength(1); j++)
            {
                int length = arrValues[i, j].Length;
                if (length > maxWidth)
                {
                    maxWidth = length;
                }
            }
        }

        return maxWidth;
    }

    private static string GetDataInTableFormat(string[,] arrValues)
    {
        string formattedString = string.Empty;

        if (arrValues == null)
            return formattedString;

        int dimension1Length = arrValues.GetLength(0);
        int dimension2Length = arrValues.GetLength(1);

        int maxCellWidth = GetMaxCellWidth(arrValues);
        int indentLength = (dimension2Length * maxCellWidth) + (dimension2Length - 1);
        //printing top line;
        formattedString = string.Format("{0}{1}{2}{3}", cellLeftTop, Indent(indentLength), cellRightTop, System.Environment.NewLine);

        for (int i = 0; i < dimension1Length; i++)
        {
            string lineWithValues = cellVerticalLine;
            string line = cellVerticalJointLeft;
            for (int j = 0; j < dimension2Length; j++)
            {
                string value = (isLeftAligned) ? arrValues[i, j].PadRight(maxCellWidth, ' ') : arrValues[i, j].PadLeft(maxCellWidth, ' ');
                lineWithValues += string.Format("{0}{1}", value, cellVerticalLine);
                line += Indent(maxCellWidth);
                if (j < (dimension2Length - 1))
                {
                    line += cellTJoint;
                }
            }
            line += cellVerticalJointRight;
            formattedString += string.Format("{0}{1}", lineWithValues, System.Environment.NewLine);
            if (i < (dimension1Length - 1))
            {
                formattedString += string.Format("{0}{1}", line, System.Environment.NewLine);
            }
        }

        //printing bottom line
        formattedString += string.Format("{0}{1}{2}{3}", cellLeftBottom, Indent(indentLength), cellRightBottom, System.Environment.NewLine);
        return formattedString;
    }

    private static string Indent(int count)
    {
        return string.Empty.PadLeft(count, '─');                 
    }

    #endregion

    #region Public Methods

    public static void PrintToStream(string[,] arrValues, StreamWriter writer)
    {
        if (arrValues == null)
            return;

        if (writer == null)
            return;

        writer.Write(GetDataInTableFormat(arrValues));
    }

    public static void PrintToConsole(string[,] arrValues)
    {
        if (arrValues == null)
            return;

        Console.WriteLine(GetDataInTableFormat(arrValues));
    }

    #endregion

    static void Main(string[] args)
    {           
        int value = 997;
        string[,] arrValues = new string[5, 5];
        for (int i = 0; i < arrValues.GetLength(0); i++)
        {
            for (int j = 0; j < arrValues.GetLength(1); j++)
            {
                value++;
                arrValues[i, j] = value.ToString();
            }
        }
        ArrayPrinter.PrintToConsole(arrValues);
        Console.ReadLine();
    }
}

4
আরো নমনীয়তা এবং ভাল কোড পুনঃব্যবহারের জন্য: 1. থেকে পরিবর্তন প্যারামিটার প্রকার StreamWriterকরার TextWriter। 2. PrintToConsoleকোডটি প্রতিস্থাপন করুন : PrintToStream(arrValues, Console.Out);3. ??? 4. লাভ!
হুবেজা

16

আমি পরিবর্তনশীল-প্রস্থের কলামগুলি চেয়েছিলাম এবং আমি বিশেষত বাক্সের অক্ষরগুলির যত্ন নিই। এছাড়াও, প্রতিটি সারির জন্য আমার অতিরিক্ত কিছু তথ্য মুদ্রণ করা দরকার।

সুতরাং অন্য কারও যদি এর প্রয়োজন হয় তবে আমি আপনাকে কয়েক মিনিট বাঁচাব:

public class TestTableBuilder
{

    public interface ITextRow
    {
        String Output();
        void Output(StringBuilder sb);
        Object Tag { get; set; }
    }

    public class TableBuilder : IEnumerable<ITextRow>
    {
        protected class TextRow : List<String>, ITextRow
        {
            protected TableBuilder owner = null;
            public TextRow(TableBuilder Owner)
            {
                owner = Owner;
                if (owner == null) throw new ArgumentException("Owner");
            }
            public String Output()
            {
                StringBuilder sb = new StringBuilder();
                Output(sb);
                return sb.ToString();
            }
            public void Output(StringBuilder sb)
            {
                sb.AppendFormat(owner.FormatString, this.ToArray());
            }
            public Object Tag { get; set; }
        }

        public String Separator { get; set; }

        protected List<ITextRow> rows = new List<ITextRow>();
        protected List<int> colLength = new List<int>();

        public TableBuilder()
        {
            Separator = "  ";
        }

        public TableBuilder(String separator)
            : this()
        {
            Separator = separator;
        }

        public ITextRow AddRow(params object[] cols)
        {
            TextRow row = new TextRow(this);
            foreach (object o in cols)
            {
                String str = o.ToString().Trim();
                row.Add(str);
                if (colLength.Count >= row.Count)
                {
                    int curLength = colLength[row.Count - 1];
                    if (str.Length > curLength) colLength[row.Count - 1] = str.Length;
                }
                else
                {
                    colLength.Add(str.Length);
                }
            }
            rows.Add(row);
            return row;
        }

        protected String _fmtString = null;
        public String FormatString
        {
            get
            {
                if (_fmtString == null)
                {
                    String format = "";
                    int i = 0;
                    foreach (int len in colLength)
                    {
                        format += String.Format("{{{0},-{1}}}{2}", i++, len, Separator);
                    }
                    format += "\r\n";
                    _fmtString = format;
                }
                return _fmtString;
            }
        }

        public String Output()
        {
            StringBuilder sb = new StringBuilder();
            foreach (TextRow row in rows)
            {
                row.Output(sb);
            }
            return sb.ToString();
        }

        #region IEnumerable Members

        public IEnumerator<ITextRow> GetEnumerator()
        {
            return rows.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return rows.GetEnumerator();
        }

        #endregion
    }



    static void Main(String[] args)
    {
        TableBuilder tb = new TableBuilder();
        tb.AddRow("When", "ID", "Name");
        tb.AddRow("----", "--", "----");

        tb.AddRow(DateTime.Now, "1", "Name1");
        tb.AddRow(DateTime.Now, "1", "Name2");

        Console.Write(tb.Output());
        Console.WriteLine();

        // or

        StringBuilder sb = new StringBuilder();
        int i = 0;
        foreach (ITextRow tr in tb)
        {
            tr.Output(sb);
            if (i++ > 1) sb.AppendLine("more stuff per line");
        }
        Console.Write(sb.ToString());
    }
}

আউটপুট:

যখন আইডি নাম
---- - ----
2/4/2013 8:37:44 পিএম 1 নাম 1
2/4/2013 8:37:44 পিএম 1 নাম 2

যখন আইডি নাম
---- - ----
2/4/2013 8:37:44 পিএম 1 নাম 1
প্রতি লাইনে আরও স্টাফ
2/4/2013 8:37:44 পিএম 1 নাম 2
প্রতি লাইনে আরও স্টাফ

9

এটি পূর্বের উত্তরের একটি উন্নতি। এটি বিভিন্ন সংখ্যক কোষ সহ পৃথক দৈর্ঘ্য এবং সারিগুলির মানগুলির জন্য সমর্থন যোগ করে। উদাহরণ স্বরূপ:

┌──────────┬─────────┬──────────────────────────┬────────────────┬─────┬───────┐
│Identifier│     Type│               Description│  CPU Credit Use│Hours│Balance│
├──────────┼─────────┼──────────────────────────┼────────────────┼─────┼───────┘
│ i-1234154│ t2.small│       This is an example.│         3263.75360│
├──────────┼─────────┼──────────────────────────┼────────────────┼─────┘
│ i-1231412│ t2.small│  This is another example.│         3089.93│
└──────────┴─────────┴──────────────────────────┴────────────────┘

কোডটি এখানে:

public class ArrayPrinter
{
    const string TOP_LEFT_JOINT = "┌";
    const string TOP_RIGHT_JOINT = "┐";
    const string BOTTOM_LEFT_JOINT = "└";
    const string BOTTOM_RIGHT_JOINT = "┘";
    const string TOP_JOINT = "┬";
    const string BOTTOM_JOINT = "┴";
    const string LEFT_JOINT = "├";
    const string JOINT = "┼";
    const string RIGHT_JOINT = "┤";
    const char HORIZONTAL_LINE = '─';
    const char PADDING = ' ';
    const string VERTICAL_LINE = "│";

    private static int[] GetMaxCellWidths(List<string[]> table)
    {
        int maximumCells = 0;
        foreach (Array row in table)
        {
            if (row.Length > maximumCells)
                maximumCells = row.Length;
        }

        int[] maximumCellWidths = new int[maximumCells];
        for (int i = 0; i < maximumCellWidths.Length; i++)
            maximumCellWidths[i] = 0;

        foreach (Array row in table)
        {
            for (int i = 0; i < row.Length; i++)
            {
                if (row.GetValue(i).ToString().Length > maximumCellWidths[i])
                    maximumCellWidths[i] = row.GetValue(i).ToString().Length;
            }
        }

        return maximumCellWidths;
    }

    public static string GetDataInTableFormat(List<string[]> table)
    {
        StringBuilder formattedTable = new StringBuilder();
        Array nextRow = table.FirstOrDefault();
        Array previousRow = table.FirstOrDefault();

        if (table == null || nextRow == null)
            return String.Empty;

        // FIRST LINE:
        int[] maximumCellWidths = GetMaxCellWidths(table);
        for (int i = 0; i < nextRow.Length; i++)
        {
            if (i == 0 && i == nextRow.Length - 1)
                formattedTable.Append(String.Format("{0}{1}{2}", TOP_LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), TOP_RIGHT_JOINT));
            else if (i == 0)
                formattedTable.Append(String.Format("{0}{1}", TOP_LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE)));
            else if (i == nextRow.Length - 1)
                formattedTable.AppendLine(String.Format("{0}{1}{2}", TOP_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), TOP_RIGHT_JOINT));
            else
                formattedTable.Append(String.Format("{0}{1}", TOP_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE)));
        }

        int rowIndex = 0;
        int lastRowIndex = table.Count - 1;
        foreach (Array thisRow in table)
        {
            // LINE WITH VALUES:
            int cellIndex = 0;
            int lastCellIndex = thisRow.Length - 1;
            foreach (object thisCell in thisRow)
            {
                string thisValue = thisCell.ToString().PadLeft(maximumCellWidths[cellIndex], PADDING);

                if (cellIndex == 0 && cellIndex == lastCellIndex)
                    formattedTable.AppendLine(String.Format("{0}{1}{2}", VERTICAL_LINE, thisValue, VERTICAL_LINE));
                else if (cellIndex == 0)
                    formattedTable.Append(String.Format("{0}{1}", VERTICAL_LINE, thisValue));
                else if (cellIndex == lastCellIndex)
                    formattedTable.AppendLine(String.Format("{0}{1}{2}", VERTICAL_LINE, thisValue, VERTICAL_LINE));
                else
                    formattedTable.Append(String.Format("{0}{1}", VERTICAL_LINE, thisValue));

                cellIndex++;
            }

            previousRow = thisRow;

            // SEPARATING LINE:
            if (rowIndex != lastRowIndex)
            {
                nextRow = table[rowIndex + 1];

                int maximumCells = Math.Max(previousRow.Length, nextRow.Length);
                for (int i = 0; i < maximumCells; i++)
                {
                    if (i == 0 && i == maximumCells - 1)
                    {
                        formattedTable.Append(String.Format("{0}{1}{2}", LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), RIGHT_JOINT));
                    }
                    else if (i == 0)
                    {
                        formattedTable.Append(String.Format("{0}{1}", LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE)));
                    }
                    else if (i == maximumCells - 1)
                    {
                        if (i > previousRow.Length)
                            formattedTable.AppendLine(String.Format("{0}{1}{2}", TOP_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), TOP_RIGHT_JOINT));
                        else if (i > nextRow.Length)
                            formattedTable.AppendLine(String.Format("{0}{1}{2}", BOTTOM_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), BOTTOM_RIGHT_JOINT));
                        else if (i > previousRow.Length - 1)
                            formattedTable.AppendLine(String.Format("{0}{1}{2}", JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), TOP_RIGHT_JOINT));
                        else if (i > nextRow.Length - 1)
                            formattedTable.AppendLine(String.Format("{0}{1}{2}", JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), BOTTOM_RIGHT_JOINT));
                        else
                            formattedTable.AppendLine(String.Format("{0}{1}{2}", JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), RIGHT_JOINT));
                    }
                    else
                    {
                        if (i > previousRow.Length)
                            formattedTable.Append(String.Format("{0}{1}", TOP_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE)));
                        else if (i > nextRow.Length)
                            formattedTable.Append(String.Format("{0}{1}", BOTTOM_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE)));
                        else
                            formattedTable.Append(String.Format("{0}{1}", JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE)));
                    }
                }
            }

            rowIndex++;
        }

        // LAST LINE:
        for (int i = 0; i < previousRow.Length; i++)
        {
            if (i == 0)
                formattedTable.Append(String.Format("{0}{1}", BOTTOM_LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE)));
            else if (i == previousRow.Length - 1)
                formattedTable.AppendLine(String.Format("{0}{1}{2}", BOTTOM_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), BOTTOM_RIGHT_JOINT));
            else
                formattedTable.Append(String.Format("{0}{1}", BOTTOM_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE)));
        }

        return formattedTable.ToString();
    }
}

4
এটি কিছু পরীক্ষার পরে দেখা গেছে যে কোনও একক কলামের ক্ষেত্রে আপনার কোড ভালভাবে পরিচালনা করে না।
বাজিলিক

6

যদি এটি কাউকে সহায়তা করে তবে এটি আমার সাধারণ প্রয়োজনের জন্য লিখেছি এমন একটি সাধারণ ক্লাস। আপনার প্রয়োজন অনুসারে আপনি এটি সহজেই পরিবর্তন করতে পারেন।

using System.Collections.Generic;
using System.Linq;

namespace Utilities
{
    public class TablePrinter
    {
        private readonly string[] titles;
        private readonly List<int> lengths;
        private readonly List<string[]> rows = new List<string[]>();

        public TablePrinter(params string[] titles)
        {
            this.titles = titles;
            lengths = titles.Select(t => t.Length).ToList();
        }

        public void AddRow(params object[] row)
        {
            if (row.Length != titles.Length)
            {
                throw new System.Exception($"Added row length [{row.Length}] is not equal to title row length [{titles.Length}]");
            }
            rows.Add(row.Select(o => o.ToString()).ToArray());
            for (int i = 0; i < titles.Length; i++)
            {
                if (rows.Last()[i].Length > lengths[i])
                {
                    lengths[i] = rows.Last()[i].Length;
                }
            }
        }

        public void Print()
        {
            lengths.ForEach(l => System.Console.Write("+-" + new string('-', l) + '-'));
            System.Console.WriteLine("+");

            string line = "";
            for (int i = 0; i < titles.Length; i++)
            {
                line += "| " + titles[i].PadRight(lengths[i]) + ' ';
            }
            System.Console.WriteLine(line + "|");

            lengths.ForEach(l => System.Console.Write("+-" + new string('-', l) + '-'));
            System.Console.WriteLine("+");

            foreach (var row in rows)
            {
                line = "";
                for (int i = 0; i < row.Length; i++)
                {
                    if (int.TryParse(row[i], out int n))
                    {
                        line += "| " + row[i].PadLeft(lengths[i]) + ' ';  // numbers are padded to the left
                    }
                    else
                    {
                        line += "| " + row[i].PadRight(lengths[i]) + ' ';
                    }
                }
                System.Console.WriteLine(line + "|");
            }

            lengths.ForEach(l => System.Console.Write("+-" + new string('-', l) + '-'));
            System.Console.WriteLine("+");
        }
    }
}

নমুনা ব্যবহার:

var t = new TablePrinter("id", "Column A", "Column B");
t.AddRow(1, "Val A1", "Val B1");
t.AddRow(2, "Val A2", "Val B2");
t.AddRow(100, "Val A100", "Val B100");
t.Print();

আউটপুট:

+-----+----------+----------+
| id  | Column A | Column B |
+-----+----------+----------+
|   1 | Val A1   | Val B1   |
|   2 | Val A2   | Val B2   |
| 100 | Val A100 | Val B100 |
+-----+----------+----------+

6

আমার গিটহাবের একটি প্রকল্প রয়েছে যা আপনি ব্যবহার করতে পারেন

https://github.com/BrunoVT1992/ কনসোল টেবিল

আপনি এটি এর মতো ব্যবহার করতে পারেন:

var table = new Table();

table.SetHeaders("Name", "Date", "Number");

for (int i = 0; i <= 10; i++)
{
    if (i % 2 == 0)
        table.AddRow($"name {i}", DateTime.Now.AddDays(-i).ToLongDateString(), i.ToString());
    else
        table.AddRow($"long name {i}", DateTime.Now.AddDays(-i).ToLongDateString(), (i * 5000).ToString());
}

Console.WriteLine(table.ToString());

এটি এই ফলাফল দেবে:

এখানে চিত্র বর্ণনা লিখুন


4
এটির জন্য আপনার ব্যতীত অন্য প্যাকেজ রয়েছে, তবে আমি আপনার আরও ভাল পছন্দ করি কারণ আউটপুট লাইন জংশনের জন্য বিশেষ অক্ষরের সাথে ভাল। এপিআই সহজ এবং খুব বেশি ধরে নেয় না (যেমন শিরোনামের প্রয়োজন), যা দুর্দান্ত। আপনি কি নুগেটে এটিকে যুক্ত করে বিবেচনা করবেন? যাইহোক ধন্যবাদ!
ফর্ম

দুর্দান্ত @ ব্রুনোভিটি ধন্যবাদ! এবং আমি একটি নুগেট চাই।
গেরহার্ড শ্রেরস

5

মার্কডাউনলগ লাইব্রেরি ব্যবহার করুন (আপনি এটি নুগেটে খুঁজে পেতে পারেন)

আপনি যে কোনও সংগ্রহে কেবলমাত্র ToMarkdownTable () এক্সটেনশনটি ব্যবহার করতে পারেন, এটি আপনার জন্য সমস্ত ফর্ম্যাটিং করে।

 Console.WriteLine(
    yourCollection.Select(s => new
                    {
                        column1 = s.col1,
                        column2 = s.col2,
                        column3 = s.col3,
                        StaticColumn = "X"
                    })
                    .ToMarkdownTable());

আউটপুট এরকম কিছু দেখাচ্ছে:

Column1  | Column2   | Column3   | StaticColumn   
--------:| ---------:| ---------:| --------------
         |           |           | X              

4
public static void ToPrintConsole(this DataTable dataTable)
    {
        // Print top line
        Console.WriteLine(new string('-', 75));

        // Print col headers
        var colHeaders = dataTable.Columns.Cast<DataColumn>().Select(arg => arg.ColumnName);
        foreach (String s in colHeaders)
        {
            Console.Write("| {0,-20}", s);
        }
        Console.WriteLine();

        // Print line below col headers
        Console.WriteLine(new string('-', 75));

        // Print rows
        foreach (DataRow row in dataTable.Rows)
        {
            foreach (Object o in row.ItemArray)
            {
                Console.Write("| {0,-20}", o.ToString());
            }
            Console.WriteLine();
        }

        // Print bottom line
        Console.WriteLine(new string('-', 75));
    }

-7

এটি ভিজুয়ালবাসিক.টনে আরও সহজ!

আপনি যদি চান যে ব্যবহারকারী কোনও টেবিলে ম্যানুয়ালি ডেটা প্রবেশ করতে সক্ষম হবেন:

Console.Write("Enter Data For Column 1: ")
    Dim Data1 As String = Console.ReadLine
    Console.Write("Enter Data For Column 2: ")
    Dim Data2 As String = Console.ReadLine

    Console.WriteLine("{0,-20} {1,-10} {2,-10}", "{Data Type}", "{Column 1}", "{Column 2}")
    Console.WriteLine("{0,-20} {1,-10} {2,-10}", "Data Entered:", Data1, Data2)

    Console.WriteLine("ENTER To Exit: ")
    Console.ReadLine()

এটিকে ঐটির মত দেখতে হবে:

এটি দেখতে (আমার ক্লিক করুন) এর মতো দেখতে হবে।


আমি ভেবেছিলাম এটি কার্যকর ছিল কারণ আমি যা চেয়েছিলাম তা হ'ল সি # তে সাধারণ কলাম প্রান্তিককরণ এবং কনসোল.উরাইটলাইন () উভয় ভাষায় একইভাবে কাজ করে।
pwrgreg007
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.