ตรวจสอบว่ามีคีย์อยู่ใน NameValueCollection หรือไม่


141

มีวิธีที่ง่ายและรวดเร็วในการตรวจสอบว่ามีคีย์อยู่ใน NameValueCollection หรือไม่โดยไม่ต้องวนซ้ำ

กำลังมองหาสิ่งที่ต้องการ Dictionary.ContainsKey () หรือคล้ายกัน

มีหลายวิธีในการแก้ปัญหานี้แน่นอน เพียงแค่สงสัยว่ามีใครสามารถช่วยเกาสมองของฉัน


เพียงใช้พจนานุกรมถ้าคุณต้องการค้นหาตามคีย์ .... BTW: คุณสามารถใช้ตัวทำดัชนีในคลาสนี้ แต่สิ่งนี้จะทำการวนซ้ำตัวเอง - ดังนั้นจึงไม่ได้รับประโยชน์
Carsten

คำตอบ:


181

จากMSDN :

คุณสมบัตินี้ส่งคืน null ในกรณีต่อไปนี้:

1) หากไม่พบคีย์ที่ระบุ

ดังนั้นคุณสามารถ:

NameValueCollection collection = ...
string value = collection[key];
if (value == null) // key doesn't exist

2) ถ้าพบคีย์ที่ระบุและค่าที่เกี่ยวข้องเป็นโมฆะ

collection[key]การโทรbase.Get()จากนั้นbase.FindEntry()ซึ่งใช้ภายในHashtableกับประสิทธิภาพ O (1)


38
คุณสมบัตินี้ส่งคืน null ในกรณีต่อไปนี้: 1) หากไม่พบคีย์ที่ระบุ และ 2) หากพบคีย์ที่ระบุและค่าที่เกี่ยวข้องนั้นเป็นโมฆะ คุณสมบัตินี้ไม่แยกความแตกต่างระหว่างสองกรณี
Steve

1
@ Andreas นั่นเป็นสาเหตุที่ดีกว่าที่จะเก็บสตริงว่างเปล่าแทน null
abatishchev

@Steve OP ไม่ได้พูดอะไรเกี่ยวกับการชนดังกล่าว
abatishchev

13
ใช่ @atishchev อย่างไรก็ตาม OP บอกว่า 'ตรวจสอบว่ามีคีย์หรือไม่' การใช้ค่า null เนื่องจากไม่มีคีย์นั้นไม่เป็นความจริง ในตอนท้ายไม่มีคำตอบใด ๆ หากไม่มีการประนีประนอม (ไม่มีการวนซ้ำให้ใช้สตริงว่าง)
Steve

@abatishchev ที่เหมือนกับว่าพูด0เท่ากับnull... sry
Andreas Niedermair

54

ใช้วิธีนี้:

private static bool ContainsKey(this NameValueCollection collection, string key)
{
    if (collection.Get(key) == null)
    {
        return collection.AllKeys.Contains(key);
    }

    return true;
}

มันมีประสิทธิภาพมากที่สุดNameValueCollectionและไม่ได้ขึ้นอยู่กับว่าการสะสมนั้นมีnullค่าหรือไม่


5
จำไว้ว่าusing System.Linq;เมื่อใช้โซลูชันนี้
jhauberg

14

ฉันไม่คิดว่าคำตอบใด ๆ เหล่านี้ค่อนข้างถูก / เหมาะสมที่สุด NameValueCollection ไม่เพียง แต่ไม่แยกความแตกต่างระหว่างค่า Null และค่าที่ขาดหายไป แต่ยังคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ด้วยการคำนึงถึงคีย์ ดังนั้นฉันคิดว่าวิธีแก้ปัญหาเต็มรูปแบบจะเป็น:

public static bool ContainsKey(this NameValueCollection @this, string key)
{
    return @this.Get(key) != null 
        // I'm using Keys instead of AllKeys because AllKeys, being a mutable array,
        // can get out-of-sync if mutated (it weirdly re-syncs when you modify the collection).
        // I'm also not 100% sure that OrdinalIgnoreCase is the right comparer to use here.
        // The MSDN docs only say that the "default" case-insensitive comparer is used
        // but it could be current culture or invariant culture
        || @this.Keys.Cast<string>().Contains(key, StringComparer.OrdinalIgnoreCase);
}

ฉันชอบวิธีนี้ ดูที่แหล่งข้อมูล NameValueCollectionBase ซึ่งเป็นค่าเริ่มต้นในการใช้ InvariantCultureIgnoreCase อย่างไรก็ตามนั่นไม่ได้หมายความว่าจะไม่มีการส่งผ่านที่แตกต่างกันไปใช้แทนคลาสใดก็ตามที่สร้างอินสแตนซ์ของ NameValueCollection
lethek

12

ใช่คุณสามารถใช้ Linq เพื่อตรวจสอบAllKeysคุณสมบัติ:

using System.Linq;
...
collection.AllKeys.Contains(key);

อย่างไรก็ตาม a Dictionary<string, string[]>จะเหมาะกว่ากับจุดประสงค์นี้มากบางทีอาจสร้างขึ้นโดยวิธีการส่วนขยาย:

public static void Dictionary<string, string[]> ToDictionary(this NameValueCollection collection) 
{
    return collection.Cast<string>().ToDictionary(key => key, key => collection.GetValues(key));
}

var dictionary = collection.ToDictionary();
if (dictionary.ContainsKey(key))
{
   ...
}

1
นั่นจะวนซ้ำไปมาทั้งคอลเลคชั่นซึ่งก็คือ O (n) ในขณะที่collection[key]ใช้ภายในHashtableซึ่งเป็น O (1)
abatishchev

4
@abatishchev แน่นอน แต่collection[key]ไม่แยกความแตกต่างระหว่างคีย์ที่ไม่มีอยู่และค่า Null ถูกเก็บไว้กับคีย์นั้น
Rich O'Kelly

นอกจากนี้คุณสามารถ preform แฮ็คสกปรกและดึงข้อมูลส่วนตัวของ Hashtable โดยใช้ Reflection
abatishchev

ฉันคิดว่านี่เป็นวิธีแก้ปัญหาโง่ ๆ หากมีใครบางคนกำลังใช้ NameValueCollection อาจเป็นเพราะเหตุผลที่พจนานุกรมไม่ได้รับการสนับสนุนเช่นมีคีย์ว่าง
Chris Marisic

0

คุณสามารถใช้Getวิธีการและตรวจสอบnullว่าวิธีการจะกลับมาnullถ้า NameValueCollection ไม่มีคีย์ที่ระบุ

ดูMSDN


คุณจำเป็นต้องรู้indexวิธีkeyการโทร ไม่ใช่เหรอ
abatishchev

0

หากขนาดของคอลเล็กชั่นมีขนาดเล็กคุณสามารถไปกับโซลูชันที่จัดทำโดย rich.okelly อย่างไรก็ตามคอลเลกชันขนาดใหญ่หมายความว่าการสร้างพจนานุกรมอาจช้ากว่าการค้นหาคีย์คอลเลกชัน

นอกจากนี้หากสถานการณ์การใช้งานของคุณกำลังค้นหากุญแจในจุดต่าง ๆ ในเวลาที่อาจมีการปรับเปลี่ยน NameValueCollection การสร้างพจนานุกรมในแต่ละครั้งอาจช้ากว่าการค้นหาชุดกุญแจ


0

นี่อาจเป็นวิธีแก้ปัญหาโดยไม่ต้องแนะนำวิธีการใหม่:

    item = collection["item"] != null ? collection["item"].ToString() : null;

0

อย่างที่คุณเห็นในแหล่งอ้างอิงNameValueCollectionสืบทอดจากNameObjectCollectionBase NameObjectCollectionBase

ดังนั้นคุณจะใช้ประเภทฐานรับ hashtable ส่วนตัวผ่านการสะท้อนและตรวจสอบว่ามันมีคีย์เฉพาะ

เพื่อให้สามารถทำงานใน Mono ได้เช่นกันคุณต้องดูว่าชื่อของ hashtable เป็นอะไรใน mono ซึ่งเป็นสิ่งที่คุณเห็นได้ที่นี่ (m_ItemsContainer) และรับ mono-field ถ้า FieldInfo เริ่มต้นเป็นโมฆะ (mono- รันไทม์)

แบบนี้

public static class ParameterExtensions
{

    private static System.Reflection.FieldInfo InitFieldInfo()
    {
        System.Type t = typeof(System.Collections.Specialized.NameObjectCollectionBase);
        System.Reflection.FieldInfo fi = t.GetField("_entriesTable", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

        if(fi == null) // Mono
            fi = t.GetField("m_ItemsContainer", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

        return fi;
    }

    private static System.Reflection.FieldInfo m_fi = InitFieldInfo();


    public static bool Contains(this System.Collections.Specialized.NameValueCollection nvc, string key)
    {
        //System.Collections.Specialized.NameValueCollection nvc = new System.Collections.Specialized.NameValueCollection();
        //nvc.Add("hello", "world");
        //nvc.Add("test", "case");

        // The Hashtable is case-INsensitive
        System.Collections.Hashtable ent = (System.Collections.Hashtable)m_fi.GetValue(nvc);
        return ent.ContainsKey(key);
    }
}

สำหรับรหัส. NET 2.0 ที่ไม่สะท้อนแสงแบบ ultra-pure คุณสามารถวนลูปผ่านคีย์แทนการใช้ตารางแฮช แต่นั่นช้า

private static bool ContainsKey(System.Collections.Specialized.NameValueCollection nvc, string key)
{
    foreach (string str in nvc.AllKeys)
    {
        if (System.StringComparer.InvariantCultureIgnoreCase.Equals(str, key))
            return true;
    }

    return false;
}

0

ใน VB มันคือ:

if not MyNameValueCollection(Key) is Nothing then
.......
end if

ใน C # ควรจะเป็น:

if (MyNameValueCollection(Key) != null) { }

ไม่แน่ใจว่าควรจะเป็นnullหรือ""แต่สิ่งนี้จะช่วย


ขออภัยที่อยู่ใน VB C # ควรจะเป็นถ้า (MyNameValueCollection (Key)! = null) {} ไม่แน่ใจว่าควรเป็นโมฆะหรือ "" แต่สิ่งนี้น่าจะช่วยได้
CodeShouldBeEasy

ผมเชื่อว่าไวยากรณ์ที่ถูกต้องจะคล้ายกับDictionaryโครงสร้างข้อมูลในขณะที่MyNameValueCollection[Key]มากกว่าMyNameValueCollection(Key)ซึ่งคาดว่าจะมีวิธีการเรียก
Blairg23

0

ฉันใช้คอลเลกชันนี้เมื่อฉันทำงานในคอลเลกชันองค์ประกอบขนาดเล็ก

ฉันคิดว่าจำเป็นต้องใช้ "พจนานุกรม" ในที่ที่มีองค์ประกอบมากมาย รหัสของฉัน:

NameValueCollection ProdIdes;
string prodId = _cfg.ProdIdes[key];
if (string.IsNullOrEmpty(prodId))
{
    ......
}

หรืออาจจะใช้สิ่งนี้:

 string prodId = _cfg.ProdIdes[key] !=null ? "found" : "not found";

0
queryItems.AllKeys.Contains(key)

โปรดทราบว่ารหัสอาจไม่ซ้ำกันและโดยทั่วไปการเปรียบเทียบจะคำนึงถึงตัวพิมพ์ หากคุณต้องการเพียงรับค่าของคีย์การจับคู่แรกและไม่สนใจเกี่ยวกับตัวพิมพ์เล็กให้ใช้สิ่งนี้:

        public string GetQueryValue(string queryKey)
        {
            foreach (string key in QueryItems)
            {
                if(queryKey.Equals(key, StringComparison.OrdinalIgnoreCase))
                    return QueryItems.GetValues(key).First(); // There might be multiple keys of the same name, but just return the first match
            }
            return null;
        }

-1
NameValueCollection n = Request.QueryString;

if (n.HasKeys())
   {
       //something
   }

ประเภทค่าตอบแทน: System.Boolean จริงถ้า NameValueCollection มีกุญแจที่ไม่เป็นโมฆะ; มิฉะนั้นเป็นเท็จ LINK


2
แม้ว่าสิ่งนี้อาจตอบคำถามได้ แต่คำอธิบายบางอย่างก็มักจะได้รับการชื่นชมโดยเฉพาะอย่างยิ่งเพื่ออธิบายว่านี่อาจเป็นทางเลือกที่ดีสำหรับคำตอบอื่น ๆ
Pac0

สิ่งนี้จะตรวจสอบว่ามีการรวบรวมคีย์ใด ๆ เลยหรือไม่ OP ขอให้มีคีย์บางตัวอยู่
Bill Tür
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.