Tuples की सूची को आसानी से कैसे शुरू करें?


287

मुझे टुपल्स बहुत पसंद हैं । वे आपको इसके लिए एक संरचना या वर्ग लिखने के बिना एक साथ प्रासंगिक जानकारी को जल्दी से समूहित करने की अनुमति देते हैं। यह बहुत ही स्थानीयकृत कोड को रीक्रिएट करते समय बहुत उपयोगी है।

हालांकि उनकी सूची को शुरू करना थोड़ा बेमानी लगता है।

var tupleList = new List<Tuple<int, string>>
{
    Tuple.Create( 1, "cow" ),
    Tuple.Create( 5, "chickens" ),
    Tuple.Create( 1, "airplane" )
};

वहाँ एक बेहतर तरीका नहीं है? मुझे डिक्शनरी इनिशियलाइज़र की तर्ज पर समाधान पसंद आएगा ।

Dictionary<int, string> students = new Dictionary<int, string>()
{
    { 111, "bleh" },
    { 112, "bloeh" },
    { 113, "blah" }
};

क्या हम एक समान सिंटैक्स का उपयोग नहीं कर सकते हैं?


2
इस मामले में आप Tuples की सूची के बजाय एक शब्दकोश का उपयोग क्यों नहीं करेंगे ?
एड एस।

17
@ ईडी एस .: ए Dictionaryडुप्लिकेट कुंजियों की अनुमति नहीं देता है।
स्टीवन ज्यूरिस

2
@ ईडीएस .: हर बार यह टू-टपल नहीं है, जहां एक आइटम हैज़ेबल / ऑर्डरेबल और यूनिक हो।

अच्छा बिंदु, डुप्लिकेट कुंजी को नोटिस नहीं किया।
एड एस।

जवाबों:


280

c # 7.0 आपको यह करने देता है:

  var tupleList = new List<(int, string)>
  {
      (1, "cow"),
      (5, "chickens"),
      (1, "airplane")
  };

यदि आपको एक की जरूरत नहीं है List, लेकिन सिर्फ एक सरणी के लिए, आप कर सकते हैं:

  var tupleList = new(int, string)[]
  {
      (1, "cow"),
      (5, "chickens"),
      (1, "airplane")
  };

और अगर आपको "Item1" और "Item2" पसंद नहीं है, तो आप कर सकते हैं:

  var tupleList = new List<(int Index, string Name)>
  {
      (1, "cow"),
      (5, "chickens"),
      (1, "airplane")
  };

या एक सरणी के लिए:

  var tupleList = new (int Index, string Name)[]
  {
      (1, "cow"),
      (5, "chickens"),
      (1, "airplane")
  };

जो आपको करने देता है: tupleList[0].IndexऔरtupleList[0].Name

फ्रेमवर्क 4.6.2 और नीचे

आपको System.ValueTupleNuget Package Manager से इंस्टॉल करना होगा ।

फ्रेमवर्क 4.7 और ऊपर

इसे फ्रेमवर्क में बनाया गया है। स्थापित करें System.ValueTuple। वास्तव में, इसे हटा दें और इसे बिन निर्देशिका से हटा दें ।

नोट: वास्तविक जीवन में, मैं गाय, मुर्गियों या हवाई जहाज के बीच चयन नहीं कर पाऊंगा। मैं सचमुच फटी रह जाती।


2
यह एक .net कोर 2.0 पर इस्तेमाल किया जा सकता है?
Алекса Јевтић

2
@ Алекса Аевтић, System.ValueTupleकोर 2.0 का समर्थन करता है। लेकिन, इसे पहले Nuget के बिना आज़माएं, क्योंकि अनावश्यक पैकेज समस्या पैदा कर सकते हैं। तो एक तरह से या दूसरे, हाँ। यदि संभव हो तो c # v7 या अधिक का उपयोग करें।
टोडरमो

1
एकदम सही जवाब! धन्यवाद!
विटॉक्स

224

हाँ! यह संभव है

संग्रह इनिशियलाइज़र का {} सिंटैक्स किसी भी IEnumerable प्रकार पर काम करता है जिसमें तर्क की सही मात्रा के साथ एक ऐड विधि है। बिना यह परेशान किए कि वह आवरणों के नीचे कैसे काम करता है, इसका मतलब है कि आप बस सूची <T> से बढ़ा सकते हैं , अपने टी को इनिशियलाइज़ करने के लिए एक कस्टम जोड़ें विधि जोड़ें , और आप कर रहे हैं!

public class TupleList<T1, T2> : List<Tuple<T1, T2>>
{
    public void Add( T1 item, T2 item2 )
    {
        Add( new Tuple<T1, T2>( item, item2 ) );
    }
}

यह आपको निम्नलिखित कार्य करने की अनुमति देता है:

var groceryList = new TupleList<int, string>
{
    { 1, "kiwi" },
    { 5, "apples" },
    { 3, "potatoes" },
    { 1, "tomato" }
};

39
एक नकारात्मक पक्ष वर्ग लिखने के लिए है। आप की तरह, मुझे ट्यूपल्स बहुत पसंद हैं क्योंकि मुझे क्लास या स्ट्रक्चर लिखना नहीं आता।
गोयडे


1
क्या यह काम groceryList[0] == groceryList[1]करता है या एक तुलना को लागू करना पड़ता है?
बाईयो

मैंने इस कोड को बनाए रखने के लिए दूसरों को बचाने के लिए ICollection पर Add विधियों के साथ एक Nuget पैकेज बनाया। पैकेज के लिए यहां देखें: nuget.org/packages/Naos.Recipes.TupleInitializers कोड के लिए यहां देखें: github.com/NaosProject/Naos.Recipes/blob/master/…। इस ".aaos" के तहत आपके समाधान में एक सीएस फ़ाइल शामिल होगी। .Recipes "फ़ोल्डर, ताकि आप एक विधानसभा निर्भरता के आसपास खींच नहीं है
SFun28

83

C # 6 इसके लिए एक नई सुविधा जोड़ता है: विस्तार विधियाँ। यह हमेशा VB.net के लिए संभव रहा है लेकिन अब C # में उपलब्ध है।

अब आपको Add()अपनी कक्षाओं के तरीकों को सीधे जोड़ने की ज़रूरत नहीं है , आप उन्हें विस्तार विधियों के रूप में लागू कर सकते हैं। जब किसी Add()विधि के साथ किसी भी प्रकार की गणना की जाती है , तो आप इसे संग्रह आरम्भिक अभिव्यक्तियों में उपयोग कर पाएंगे। तो आपको सूचियों से स्पष्ट रूप से अब और ( जैसा कि किसी अन्य उत्तर में उल्लेख किया गया है ) प्राप्त करने की आवश्यकता नहीं है , आप बस इसे बढ़ा सकते हैं।

public static class TupleListExtensions
{
    public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
            T1 item1, T2 item2)
    {
        list.Add(Tuple.Create(item1, item2));
    }

    public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> list,
            T1 item1, T2 item2, T3 item3)
    {
        list.Add(Tuple.Create(item1, item2, item3));
    }

    // and so on...
}

यह आपको इसे लागू करने वाले किसी भी वर्ग पर करने की अनुमति देगा IList<>:

var numbers = new List<Tuple<int, string>>
{
    { 1, "one" },
    { 2, "two" },
    { 3, "three" },
    { 4, "four" },
    { 5, "five" },
};
var points = new ObservableCollection<Tuple<double, double, double>>
{
    { 0, 0, 0 },
    { 1, 2, 3 },
    { -4, -2, 42 },
};

बेशक आप टुपल्स के संग्रह को बढ़ाने के लिए प्रतिबंधित नहीं हैं, यह किसी भी विशिष्ट प्रकार के संग्रह के लिए हो सकता है, जिसके लिए आप विशेष वाक्यविन्यास चाहते हैं।

public static class BigIntegerListExtensions
{
    public static void Add(this IList<BigInteger> list,
        params byte[] value)
    {
        list.Add(new BigInteger(value));
    }

    public static void Add(this IList<BigInteger> list,
        string value)
    {
        list.Add(BigInteger.Parse(value));
    }
}

var bigNumbers = new List<BigInteger>
{
    new BigInteger(1), // constructor BigInteger(int)
    2222222222L,       // implicit operator BigInteger(long)
    3333333333UL,      // implicit operator BigInteger(ulong)
    { 4, 4, 4, 4, 4, 4, 4, 4 },               // extension Add(byte[])
    "55555555555555555555555555555555555555", // extension Add(string)
};

C # 7 भाषा में निर्मित टुपल्स के समर्थन में जोड़ रहा होगा, हालांकि वे एक अलग प्रकार ( System.ValueTupleइसके बजाय) के होंगे। इसलिए वैल्यू टुपल्स के लिए ओवरलोड्स को जोड़ना अच्छा होगा, इसलिए आपके पास इन्हें इस्तेमाल करने का विकल्प होगा। दुर्भाग्य से, दोनों के बीच कोई निहित रूपांतरण नहीं है।

public static class ValueTupleListExtensions
{
    public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
        ValueTuple<T1, T2> item) => list.Add(item.ToTuple());
}

इस तरह सूची आरंभीकरण भी अच्छा लगेगा।

var points = new List<Tuple<int, int, int>>
{
    (0, 0, 0),
    (1, 2, 3),
    (-1, 12, -73),
};

लेकिन इस सब परेशानी से गुजरने के बजाय, ValueTupleविशेष रूप से उपयोग करने के लिए स्विच करना बेहतर हो सकता है ।

var points = new List<(int, int, int)>
{
    (0, 0, 0),
    (1, 2, 3),
    (-1, 12, -73),
};

मैंने अंततः अपनी लाइब्रेरी को C # 6.0 में अपडेट करते समय इस पर एक अच्छी नज़र रखी। हालाँकि यह एक नज़र में अच्छा लगता है, मैं इस पर अपना पहले का पोस्ट किया हुआ समाधान पसंद करता हूँ क्योंकि मुझे इससे TupleList<int, string>.अधिक पठनीय लगता है List<Tuple<int, string>>
स्टीवन ज्यूरिस

1
यह कुछ ऐसा है जो एक प्रकार का उपनाम ठीक कर सकता है। अधिग्रहित उपनाम खुद सामान्य नहीं हो सकता है जो बेहतर हो सकता है। using TupleList = System.Collections.Generic.List<System.Tuple<int, string>>;
जेफ मर्काडो

मैंने इस कोड को बनाए रखने के लिए दूसरों को बचाने के लिए ICollection पर Add विधियों के साथ एक Nuget पैकेज बनाया। पैकेज के लिए यहां देखें: nuget.org/packages/Naos.Recipes.TupleInitializers कोड के लिए यहां देखें: github.com/NaosProject/Naos.Recipes/blob/master/…। इस ".aaos" के तहत आपके समाधान में एक सीएस फ़ाइल शामिल होगी। .Recipes "फ़ोल्डर, ताकि आप एक विधानसभा निर्भरता के आसपास खींच नहीं है
SFun28

42

आप इसे हर बार कंस्ट्रक्टर को कॉल करके कर सकते हैं

var tupleList = new List<Tuple<int, string>>
{
    new Tuple<int, string>(1, "cow" ),
    new Tuple<int, string>( 5, "chickens" ),
    new Tuple<int, string>( 1, "airplane" )
};

6
मुझे काम करने के लिए मूल कोड नहीं मिला, इसलिए मैंने इसमें संशोधन किया है कि मुझे क्या लगता है कि यह होना चाहिए ... जो इस पर आपकी राय को उलट सकता है कि क्या वाक्यविन्यास "आखिरकार थोड़ा बेहतर है :)
onedaywhen

5
Tuple.Createइसके बजाय कम से कम उपयोग करें और आप टाइप तर्क वितर्क कर सकते हैं
डेव कूसिन्यू

28

पुराना सवाल, लेकिन यह वही है जो मैं आमतौर पर चीजों को थोड़ा अधिक पठनीय बनाने के लिए करता हूं:

Func<int, string, Tuple<int, string>> tc = Tuple.Create;

var tupleList = new List<Tuple<int, string>>
{
    tc( 1, "cow" ),
    tc( 5, "chickens" ),
    tc( 1, "airplane" )
};

.NET के पुराने संस्करणों पर भी काम करता है!
एड बेयेट्स

1

सुपर डुपर ओल्ड मुझे पता है, लेकिन मैं सी # 7 का उपयोग करने के तरीकों के साथ लिनक और निरंतरता लैम्ब्डा का उपयोग करने पर अपना टुकड़ा जोड़ूंगा। मैं एक वर्ग में पुन: उपयोग करने पर डीटीओ और अनाम अनुमानों के प्रतिस्थापन के रूप में टुपल्स नाम का उपयोग करने का प्रयास करता हूं। हाँ, मॉकिंग और टेस्टिंग के लिए आपको अभी भी कक्षाओं की आवश्यकता है लेकिन इनलाइन चीजों को करना और कक्षा में इधर-उधर से गुजरना अच्छा है, यह नया विकल्प IMHO है। आप उनसे तुरंत इन्कार कर सकते हैं

  1. प्रत्यक्ष तात्कालिकता
var items = new List<(int Id, string Name)> { (1, "Me"), (2, "You")};
  1. एक मौजूदा संग्रह से बाहर, और अब आप अनाम टंकण के समान अच्छी तरह से टाइप किए गए ट्यूपल्स वापस कर सकते हैं।
public class Hold
{
    public int Id { get; set; }
    public string Name { get; set; }
}

//In some method or main console app:
var holds = new List<Hold> { new Hold { Id = 1, Name = "Me" }, new Hold { Id = 2, Name = "You" } };
var anonymousProjections = holds.Select(x => new { SomeNewId = x.Id, SomeNewName = x.Name });
var namedTuples = holds.Select(x => (TupleId: x.Id, TupleName: x.Name));
  1. बाद में समूह के तरीकों के साथ ट्यूपलों का पुन: उपयोग करें या अन्य तर्क में उन्हें इनलाइन बनाने के लिए एक विधि का उपयोग करें:
//Assuming holder class above making 'holds' object
public (int Id, string Name) ReturnNamedTuple(int id, string name) => (id, name);
public static List<(int Id, string Name)> ReturnNamedTuplesFromHolder(List<Hold> holds) => holds.Select(x => (x.Id, x.Name)).ToList();
public static void DoSomethingWithNamedTuplesInput(List<(int id, string name)> inputs) => inputs.ForEach(x => Console.WriteLine($"Doing work with {x.id} for {x.name}"));

var namedTuples2 = holds.Select(x => ReturnNamedTuple(x.Id, x.Name));
var namedTuples3 = ReturnNamedTuplesFromHolder(holds);
DoSomethingWithNamedTuplesInput(namedTuples.ToList());

आप मुझे बूढ़ा होने का एहसास कराएं। :) मुझे यहाँ कुछ याद आ रहा है, लेकिन 'होल्ड' को इनिशियलाइज़ करना बिल्कुल भी संक्षिप्त नहीं है। यह प्रश्न का सटीक बिंदु था।
स्टीवन ज्यूरिस

@Steven Jeuris नहीं, आप सही थे मैंने कॉपी किया और प्वाइंट 1 के लिए गलत कोड को पेस्ट कर दिया। मुझे 'सबमिट' करने से पहले थोड़ा धीमा जाना होगा।
djangojazz

0

टुपल्स क्यों पसंद हैं? यह अनाम प्रकारों की तरह है: कोई नाम नहीं। डेटा की संरचना को नहीं समझ सकते।

मुझे क्लासिक कक्षाएं पसंद हैं

class FoodItem
{
     public int Position { get; set; }
     public string Name { get; set; }
}

List<FoodItem> list = new List<FoodItem>
{
     new FoodItem { Position = 1, Name = "apple" },
     new FoodItem { Position = 2, Name = "kiwi" }
};

3
जैसा कि मैंने कहा: "वे आपको इसके लिए एक संरचना या कक्षा लिखने के बिना एक साथ प्रासंगिक जानकारी को जल्दी से समूहित करने की अनुमति देते हैं।" यदि यह वर्ग पूरी तरह से हेल्पर डेटा संरचना के रूप में एकल विधि के भीतर उपयोग किया जाता है, तो मैं ट्यूपल्स का उपयोग करना पसंद करता हूं, इसलिए किसी अनावश्यक वर्ग के साथ नाम स्थान को आबाद करने के लिए नहीं।
स्टीवन ज्यूरिस

1
आप पुराने ट्यूपल वर्ग (संरचना नहीं) के बारे में सोच रहे हैं। C # 7 ने स्ट्रक्चर-बेस्ड टुपल्स (नए ValueTuple प्रकार द्वारा समर्थित) जो कि नाम हो सकते हैं, ताकि आप डेटा की संरचना को समझ सकें
स्टीव नाइल्स

0

मुझे लगता है कि एक तकनीक थोड़ी आसान है और जिसका उल्लेख यहां पहले नहीं किया गया है:

var asdf = new [] { 
    (Age: 1, Name: "cow"), 
    (Age: 2, Name: "bird")
}.ToList();

मुझे लगता है कि थोड़ा क्लीनर है:

var asdf = new List<Tuple<int, string>> { 
    (Age: 1, Name: "cow"), 
    (Age: 2, Name: "bird")
};

स्वाद के लिए और अधिक नीचे आता है कि क्या आप स्पष्ट रूप से प्रकारों का उल्लेख करना पसंद करते हैं या नहीं, उसी व्यर्थ में उपयोग करने के लिए varया नहीं। मैं व्यक्तिगत रूप से स्पष्ट टाइपिंग पसंद करता हूं (जब यह निर्माणकर्ता में डुप्लिकेट नहीं है)।
स्टीवन ज्यूरिस

-4
    var colors = new[]
    {
        new { value = Color.White, name = "White" },
        new { value = Color.Silver, name = "Silver" },
        new { value = Color.Gray, name = "Gray" },
        new { value = Color.Black, name = "Black" },
        new { value = Color.Red, name = "Red" },
        new { value = Color.Maroon, name = "Maroon" },
        new { value = Color.Yellow, name = "Yellow" },
        new { value = Color.Olive, name = "Olive" },
        new { value = Color.Lime, name = "Lime" },
        new { value = Color.Green, name = "Green" },
        new { value = Color.Aqua, name = "Aqua" },
        new { value = Color.Teal, name = "Teal" },
        new { value = Color.Blue, name = "Blue" },
        new { value = Color.Navy, name = "Navy" },
        new { value = Color.Pink, name = "Pink" },
        new { value = Color.Fuchsia, name = "Fuchsia" },
        new { value = Color.Purple, name = "Purple" }
    };
    foreach (var color in colors)
    {
        stackLayout.Children.Add(
            new Label
            {
                Text = color.name,
                TextColor = color.value,
            });
        FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
    }

this is a Tuple<Color, string>

टुपल के साथ आपको मूल्य / नाम सिंटैक्स कैसे मिलता है?
एंड्रियास रीफ

कंपाइलर बताता है कि अनाम प्रकार टुपल के लिए अभिसारी रूप से परिवर्तनीय नहीं हैं
cthepenier
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.