473,788 Members | 2,825 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

find closest item in keyed collection

Does the .NET framework provide a class which will find the item in
the collection with a key which is closest ( greater than or equal,
less than or equal ) to the keys of the collection?

ex: collection keys are 20, 30, 40, 50, 60, 70, 80

find key which is >= 35.

would return the 30 key.

thanks,
Dec 17 '07
22 4728
Liz

// Array.BinarySea rch (find next closest match)

Array i2 = Array.CreateIns tance(typeof(st ring), 8);

i2.SetValue("An ne", 0);
i2.SetValue("Bo b", 1);
i2.SetValue("Ch ris", 2);
i2.SetValue("Do nna", 3);
i2.SetValue("El izabeth", 4);
i2.SetValue("Gl enn", 5);
i2.SetValue("Fr anklin", 6);
i2.SetValue("He lene", 7);

int j = Array.BinarySea rch(i2, "DonnaB");
if (j<0)
j = ~j;

MessageBox.Show (i2.GetValue(j) .ToString()); // ==Elizabeth


"Ben Voigt [C++ MVP]" <rb*@nospam.nos pamwrote in message
news:O6******** ******@TK2MSFTN GP05.phx.gbl...
>
"Marc Gravell" <ma**********@g mail.comwrote in message
news:%2******** ********@TK2MSF TNGP03.phx.gbl. ..
>One-way searches are fortunately easier than 2-way proximity... you get
to stop sooner ;-p
If this is volume usage, then the LINQ approach I posted earlier would be
a poor choice (it would sort each time); Ben mentioned a SortedList which
may be helpful... I can't only see equality methods myself, but you could
perhaps simply walk the list until you find one that is 2022 and return
the previous (if you see what I mean...).

Ack! SortedList.Inde xOfKey doesn't return the index for not found items,
while List.BinarySear ch does. But you can't run BinarySearch on a sorted
list! An extension method would be good...

So either reimplement BinarySearch to work on a SortedList or use List and
List.BinarySear ch and keep the list sorted yourself.
>>
Of course, if you are adding to the list in sequence, you could just use
a regular list, and do the same walk.
If you are adding to the list while iterating, it is probably just the
last element.

Just for completeness (to contrast to my prior post); in LINQ terms this
is:

IDictionary<int , stringdata = new SortedList<int, string{
{20, "a"}, {30, "b"}, {40, "c"}, {50, "d"},
{60, "e"}, {70, "f"}, {80, "g"}
};
KeyValuePair<in t, stringresult =
data.TakeWhile( x =x.Key <= 35).Last();

(I'm using TakeWhile here since we know the data is sorted; hence it will
stop reading when it finds something that doesn't meet the <= 35
condition).

Of course, if you are generally accessing recent data you may be better
keeping the list inverted (perhaps even just a List<Tand Insert at 0;
or use a custom comparer to automatically invert the list in-place [very
easy]) and check for the first match:

KeyValuePair<in t, stringresult =
data.SkipWhile( x =x.Key 35).First();

Marc


Dec 18 '07 #11
Ben, Tested that on the original q, as I understand it, the "close
find" shuld give 40 if asked 39...

Array i2 = Array.CreateIns tance(typeof(sh ort),7);

// given 20, 30, 40, 50, 60, 70, 80

i2.SetValue((sh ort)20, 0);
i2.SetValue((sh ort)30, 1);
i2.SetValue((sh ort)40, 2);
i2.SetValue((sh ort)50, 3);
i2.SetValue((sh ort)60, 4);
i2.SetValue((sh ort)70, 5);
i2.SetValue((sh ort)80, 6);

// given 35
int j = Array.BinarySea rch(i2, (short)35);
if (j < -1)
j = ~j-1;

Console.WriteLi ne("35 -" +
i2.GetValue(j). ToString()); // 30

// testing low 10
j = Array.BinarySea rch(i2, (short)10);
if (j < -1)
j = ~j - 1;
else // Oops
j = 0;
Console.WriteLi ne("10 -" +
i2.GetValue(j). ToString()); // 20

// testing high 100
j = Array.BinarySea rch(i2, (short)100);
if (j < -1)
j = ~j - 1;

Console.WriteLi ne("100 -" +
i2.GetValue(j). ToString()); // 80

// testing close 39
j = Array.BinarySea rch(i2, (short)39);
if (j < -1)
j = ~j - 1;

Console.WriteLi ne("39 -" +
i2.GetValue(j). ToString()); // 30 = Fail, should return 40 or what?

//CY
Dec 19 '07 #12
Liz

<ch*******@gmai l.comwrote in message
news:1d******** *************** ***********@1g2 000hsl.googlegr oups.com...
Ben, Tested that on the original q, as I understand it, the "close
find" shuld give 40 if asked 39...
that was my doing, not Ben's; yes, you should get 40 if the predicate is
39, and you do; what I'm not clear on is why you're subtracting 1 from the
bitwise complement of the result ... and why you're testing for "j < -1"
if (j < -1)
j = ~j-1;
should be:

if (j < 0)
j = ~j;

BUT, I should have done some bounds checking where the predicate is greater
than the highest valued item in the array:

if (j < i2.Length)
MessageBox.Show (i2.GetValue(j) .ToString());
else
MessageBox.Show ("Cannot return a value");

>
Array i2 = Array.CreateIns tance(typeof(sh ort),7);

// given 20, 30, 40, 50, 60, 70, 80

i2.SetValue((sh ort)20, 0);
i2.SetValue((sh ort)30, 1);
i2.SetValue((sh ort)40, 2);
i2.SetValue((sh ort)50, 3);
i2.SetValue((sh ort)60, 4);
i2.SetValue((sh ort)70, 5);
i2.SetValue((sh ort)80, 6);

// given 35
int j = Array.BinarySea rch(i2, (short)35);
if (j < -1)
j = ~j-1;

Console.WriteLi ne("35 -" +
i2.GetValue(j). ToString()); // 30

// testing low 10
j = Array.BinarySea rch(i2, (short)10);
if (j < -1)
j = ~j - 1;
else // Oops
j = 0;
Console.WriteLi ne("10 -" +
i2.GetValue(j). ToString()); // 20

// testing high 100
j = Array.BinarySea rch(i2, (short)100);
if (j < -1)
j = ~j - 1;

Console.WriteLi ne("100 -" +
i2.GetValue(j). ToString()); // 80

// testing close 39
j = Array.BinarySea rch(i2, (short)39);
if (j < -1)
j = ~j - 1;

Console.WriteLi ne("39 -" +
i2.GetValue(j). ToString()); // 30 = Fail, should return 40 or what?

//CY

Dec 19 '07 #13

"Liz" <li*@tiredofspa m.comwrote in message
news:%2******** ********@TK2MSF TNGP03.phx.gbl. ..
>
<ch*******@gmai l.comwrote in message
news:1d******** *************** ***********@1g2 000hsl.googlegr oups.com...
>Ben, Tested that on the original q, as I understand it, the "close
find" shuld give 40 if asked 39...
BinarySearch doesn't give you the closest element by default, it gives you
the address of the closest greater element. The element right before is
(due to sorting) the closest smaller element, and you may therefore use
whichever of the two you prefer. This is still O(log N), because there is
no extra expense as the length of the list increases.

If your list is less than about 64 elements you are better off with a single
pass linear search.

If your elements are fairly evenly distributed (or according to a known
distribution) then you can do much better than a binary search by estimating
the location of the element sought.
>
that was my doing, not Ben's; yes, you should get 40 if the predicate is
39, and you do; what I'm not clear on is why you're subtracting 1 from
the bitwise complement of the result ... and why you're testing for "j
< -1"
>if (j < -1)
j = ~j-1;

should be:

if (j < 0)
j = ~j;

BUT, I should have done some bounds checking where the predicate is
greater than the highest valued item in the array:

if (j < i2.Length)
MessageBox.Show (i2.GetValue(j) .ToString());
else
MessageBox.Show ("Cannot return a value");

>>
Array i2 = Array.CreateIns tance(typeof(sh ort),7);

// given 20, 30, 40, 50, 60, 70, 80

i2.SetValue((sh ort)20, 0);
i2.SetValue((sh ort)30, 1);
i2.SetValue((sh ort)40, 2);
i2.SetValue((sh ort)50, 3);
i2.SetValue((sh ort)60, 4);
i2.SetValue((sh ort)70, 5);
i2.SetValue((sh ort)80, 6);

// given 35
int j = Array.BinarySea rch(i2, (short)35);
if (j < -1)
j = ~j-1;

Console.WriteLi ne("35 -" +
i2.GetValue(j) .ToString()); // 30

// testing low 10
j = Array.BinarySea rch(i2, (short)10);
if (j < -1)
j = ~j - 1;
else // Oops
j = 0;
Console.WriteLi ne("10 -" +
i2.GetValue(j) .ToString()); // 20

// testing high 100
j = Array.BinarySea rch(i2, (short)100);
if (j < -1)
j = ~j - 1;

Console.WriteLi ne("100 -" +
i2.GetValue(j) .ToString()); // 80

// testing close 39
j = Array.BinarySea rch(i2, (short)39);
if (j < -1)
j = ~j - 1;

Console.WriteLi ne("39 -" +
i2.GetValue(j) .ToString()); // 30 = Fail, should return 40 or what?

//CY


Dec 19 '07 #14
"Liz" <li*@tiredofspa m.comwrote in message
news:uC******** ******@TK2MSFTN GP03.phx.gbl...
>
// Array.BinarySea rch (find next closest match)

Array i2 = Array.CreateIns tance(typeof(st ring), 8);

i2.SetValue("An ne", 0);
i2.SetValue("Bo b", 1);
i2.SetValue("Ch ris", 2);
i2.SetValue("Do nna", 3);
i2.SetValue("El izabeth", 4);
i2.SetValue("Gl enn", 5);
i2.SetValue("Fr anklin", 6);
i2.SetValue("He lene", 7);
<snip>
<off topic>
Why would you declare an array of strings with that syntax?
I mean, it works, but why subject yourself to that icky looking code.
How about
string[] X = new string[]{"Anne", "Bob", "Chris", "Donna", "Elizabeth" ,
"Glenn", "Franklin", "Helene"};

Just curious
Bill
Dec 20 '07 #15
Liz

"Bill Butler" <qw****@asdf.co mwrote in message
news:Dikaj.8038 $8y4.8009@trndd c07...
>Array i2 = Array.CreateIns tance(typeof(st ring), 8);

i2.SetValue("A nne", 0);
i2.SetValue("B ob", 1);
i2.SetValue("C hris", 2);
i2.SetValue("D onna", 3);
i2.SetValue("E lizabeth", 4);
i2.SetValue("G lenn", 5);
i2.SetValue("F ranklin", 6);
i2.SetValue("H elene", 7);
Why would you declare an array of strings with that syntax?
I mean, it works, but why subject yourself to that icky looking code.
How about
string[] X = new string[]{"Anne", "Bob", "Chris", "Donna", "Elizabeth" ,
"Glenn", "Franklin", "Helene"};

The original question presented was how to get a "soft" match in an array
using BinarySearch, i.e.: if no match, return the next highest value in the
array; so far as I know, there's no (straightforwar d) way to get there from
string[] x = {..,..,.. } syntax ...

who cares about the "ickiness" of syntax? it's all machine code out the
door; in a real-world example, you'd iterate it up with no muss, no fuss in
5-10 lines of code wrapping array.SetValue( a,n) in a loop ... but if you
have a better solution to do the soft match, I'm all ears ... assume the
array would be of significant size, not length = 8 ...

Dec 20 '07 #16
"Liz" <li*@tiredofspa m.comwrote in message
news:Oe******** ******@TK2MSFTN GP04.phx.gbl...
>
"Bill Butler" <qw****@asdf.co mwrote in message
news:Dikaj.8038 $8y4.8009@trndd c07...
>>Array i2 = Array.CreateIns tance(typeof(st ring), 8);

i2.SetValue(" Anne", 0);
i2.SetValue(" Bob", 1);
i2.SetValue(" Chris", 2);
i2.SetValue(" Donna", 3);
i2.SetValue(" Elizabeth", 4);
i2.SetValue(" Glenn", 5);
i2.SetValue(" Franklin", 6);
i2.SetValue(" Helene", 7);
>Why would you declare an array of strings with that syntax?
I mean, it works, but why subject yourself to that icky looking code.
>How about
string[] X = new string[]{"Anne", "Bob", "Chris", "Donna",
"Elizabeth" , "Glenn", "Franklin", "Helene"};


The original question presented was how to get a "soft" match in an
array using BinarySearch, i.e.: if no match, return the next highest
value in the array; so far as I know, there's no (straightforwar d)
way to get there from string[] x = {..,..,.. } syntax ...
I did Add "off topic" right before I asked (which you edited out).
I have no quibble over the Binary search suggestion, It is what I would
have suggested.
My question has nothing to do with that.
I simply wanted to know why you would Array.CreateIns tance instead of
the more common syntax for array creation?
Is there some benefit that I am unaware of?

As I said "Just Curious"

Bill
Dec 20 '07 #17
Liz

"Bill Butler" <qw****@asdf.co mwrote in message
news:jQlaj.2881 4$JW4.27575@trn ddc05...
>>How about
string[] X = new string[]{"Anne", "Bob", "Chris", "Donna", "Elizabeth" ,
"Glenn", "Franklin", "Helene"};
>The original question presented was how to get a "soft" match in an array
using BinarySearch, i.e.: if no match, return the next highest value in
the array; so far as I know, there's no (straightforwar d) way to get
there from string[] x = {..,..,.. } syntax ...
I did Add "off topic" right before I asked (which you edited out).
I have no quibble over the Binary search suggestion, It is what I would
have suggested.
My question has nothing to do with that.
I simply wanted to know why you would Array.CreateIns tance instead of the
more common syntax for array creation?
Is there some benefit that I am unaware of?
Bill,

First of all, your comment was not off-topic ....
I simply wanted to know why you would Array.CreateIns tance instead of the
more common syntax for array creation?
that's what I responded to .... you can't do this:

string[] X = new string[]{"Anne", "Bob", "Chris", "Donna",
"Elizabeth" , "Glenn", "Franklin", "Helene"};

X.BinarySearch( "DonnaZ");

Do you know a way to initiate a BinarySearch using the array initialization
syntax you propose here?



Dec 20 '07 #18

"Liz" <li*@tiredofspa m.comwrote in message
news:%2******** *******@TK2MSFT NGP03.phx.gbl.. .
>
"Bill Butler" <qw****@asdf.co mwrote in message
news:jQlaj.2881 4$JW4.27575@trn ddc05...
<snip>
Bill,

First of all, your comment was not off-topic ....
>I simply wanted to know why you would Array.CreateIns tance instead of
the more common syntax for array creation?

that's what I responded to .... you can't do this:

string[] X = new string[]{"Anne", "Bob", "Chris", "Donna",
"Elizabeth" , "Glenn", "Franklin", "Helene"};

X.BinarySearch( "DonnaZ");

Do you know a way to initiate a BinarySearch using the array
initialization syntax you propose here?
Array.BinarySea rch(X,"DonnaZ") ;
Dec 20 '07 #19
On Wed, 19 Dec 2007 20:13:53 -0800, Liz <li*@tiredofspa m.comwrote:
[...]
>I simply wanted to know why you would Array.CreateIns tance instead of
the
more common syntax for array creation?

that's what I responded to .... you can't do this:

string[] X = new string[]{"Anne", "Bob", "Chris", "Donna",
"Elizabeth" , "Glenn", "Franklin", "Helene"};

X.BinarySearch( "DonnaZ");
You can't do that even initializing the array as you did. There's no
Array.BinarySea rch() overload that takes a single parameter. There's not
even an instance method version of BinarySearch.
Do you know a way to initiate a BinarySearch using the array
initialization
syntax you propose here?
There are a number of overloads for Array.BinarySea rch. Any of them would
work equally well, whether you initialize the array using the syntax you
posted or the syntax Bill posted. For example:

Array.BinarySea rch(X, "DonnaZ");

I'm with Bill. I don't see any advantage at all to using the syntax you
posted. It's incredibly unwieldy, difficult to read, and doesn't even
provide a typed array. I'm at a loss to understand why you'd prefer that
syntax to the normal array declaration syntax.

Pete
Dec 20 '07 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
4075
by: panik | last post by:
Hi, I have a custom collection that implements CollectionBase. The collection is called Sensors and contains a list of Sensor objects. There is the usual index using an integer (Sensors). Is there a way of using a custom indexer (for example Sensors) that does *not* need to loop through each item in the collection and compare them?
13
12323
by: mike | last post by:
I have ListArray with number in Eg: 1, 1.456, 2.43, 4, 6.78 next i have a decimal variable containing one number EG: 1.786 Could someone please tell me how i find the "closest match" number below the decimal variable from the arraylist. Thanks ever so much in advance
2
5575
by: Terry Olsen | last post by:
I'm using a listview control with 2 columns (in detail view). I need to find an item by text so that I can add a subitem to it. I haven't been successful so far. Any help is appreciated.
1
3037
by: SP | last post by:
I have created an abstract class inheriting from KeyedCollection<long, TItemto use as a base class for my collections. In some derived classes I am providing a new indexer property for the key (long). I need to access my collection by index and by key however the new long indexer is used for BOTH int and long, i.e. myCollection will use the long indexer NOT the base classes int indexer. Why is that? The workaround is to also define a new...
6
1735
by: Hyun-jik Bae | last post by:
Is there any way how to get the item which has the most similar key in key-value collection object such as Dictionary<or SortedDictionary<> although there is no matching key? If there is none, is there any substitution class for enabling this? Please reply. Thanks in advance. Hyun-jik Bae
2
4919
by: Jon Slaughter | last post by:
topic says it all? Is there any simple way? msdn says that the keyed collection is build from both a sortedlist and sorted dictionary. http://msdn2.microsoft.com/en-us/library/5z658b67.aspx (well, it doesn't say that specifically but it says it when talking about the sorted versions so I'm not sure) I've found this
0
9656
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10175
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10112
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9969
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8993
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5399
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5536
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4070
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2894
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.