comparison string object to string array...

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • David  Lazos

    comparison string object to string array...

    Hi All,

    I use Contains method of String object to determine if a string variable
    has another string, like that.
    *************** ************
    ipAddress.Conta ins("127.0.0")
    *************** *************

    supposing that, there is a string array like

    string[] aryIPAddress = {"127.0.0.", "192.168.1.","6 6.249.71."};

    Is it possible to determine if any string in this array occurs in a String
    Object without using foreach or for patterns ?

    Thanks in advance..


  • Jon Skeet [C# MVP]

    #2
    Re: comparison string object to string array...

    On Jul 12, 11:38 am, "David Lazos" <D...@DL.comwro te:
    I use Contains method of String object to determine if  a string variable
    has another string, like that.
    *************** ************
    ipAddress.Conta ins("127.0.0")
    *************** *************
    >
    supposing that,  there is a string array like
    >
    string[] aryIPAddress = {"127.0.0.", "192.168.1.","6 6.249.71."};
    >
    Is it possible to determine if any string in this array occurs in a String
    Object  without using foreach or for patterns ?
    If you're using C# 3 and .NET 3.5, you could do:

    if (aryIPAddres.An y(candidate =candidate.Cont ains("127.0.0") ))

    (You might want to use StartsWith instead of Contains.)

    Of course, this still uses for/foreach internally - if you can't
    use .NET 3.5 you can easily write your own method to do it.

    Jon

    Comment

    • Pavel Minaev

      #3
      Re: comparison string object to string array...

      On Jul 12, 3:30 pm, "Jon Skeet [C# MVP]" <sk...@pobox.co mwrote:
      On Jul 12, 11:38 am, "David  Lazos" <D...@DL.comwro te:
      >
      I use Contains method of String object to determine if  a string variable
      has another string, like that.
      *************** ************
      ipAddress.Conta ins("127.0.0")
      *************** *************
      >
      supposing that,  there is a string array like
      >
      string[] aryIPAddress = {"127.0.0.", "192.168.1.","6 6.249.71."};
      >
      Is it possible to determine if any string in this array occurs in a String
      Object  without using foreach or for patterns ?
      >
      If you're using C# 3 and .NET 3.5, you could do:
      >
      if (aryIPAddres.An y(candidate =candidate.Cont ains("127.0.0") ))
      If I understand the original poster correctly, he actually wanted to
      do it the other way around, that is:

      aryIPAddress.An y(candidate =ipAddress.Cont ains(candidate) )

      Still, for a sufficiently large list of substrings to match, it's not
      so good - since a lookup from beginning to end of the string is done
      for every element of the list. In this case, I'd recommend converting
      the list of substrings to a Regex, and then use Regex.Match:

      var regex = new Regex(string.Jo in("|", aryIPAddres.Sel ect(s =>
      Regex.Escape(s) ).ToArray()));
      if (regex.IsMatch( ipAddress)) { ... }

      It will be somewhat faster, because it will reduce the list of
      candidate substrings as it matches - e.g. as soon as it sees that the
      first digit is "2", it will not even bother trying to match all IPs
      that start with anything else.



      Comment

      • Jon Skeet [C# MVP]

        #4
        Re: comparison string object to string array...

        On Jul 12, 12:48 pm, Pavel Minaev <int...@gmail.c omwrote:
        if (aryIPAddres.An y(candidate =candidate.Cont ains("127.0.0") ))
        >
        If I understand the original poster correctly, he actually wanted to
        do it the other way around, that is:
        >
        aryIPAddress.An y(candidate =ipAddress.Cont ains(candidate) )
        That's very possible - I wasn't entirely sure which way round it was
        meant to be.
        Still, for a sufficiently large list of substrings to match, it's not
        so good - since a lookup from beginning to end of the string is done
        for every element of the list. In this case, I'd recommend converting
        the list of substrings to a Regex, and then use Regex.Match:
        >
        var regex = new Regex(string.Jo in("|", aryIPAddres.Sel ect(s =>
        Regex.Escape(s) ).ToArray()));
        if (regex.IsMatch( ipAddress)) { ... }
        >
        It will be somewhat faster, because it will reduce the list of
        candidate substrings as it matches - e.g. as soon as it sees that the
        first digit is "2", it will not even bother trying to match all IPs
        that start with anything else.
        On the other hand, it has to join all the strings together to start
        with, escape them all, and then parse the generated regular
        expression.

        In addition, the code is considerably more complicated to understand.

        I'd certainly go for the simpler way to start with, and then do
        concrete performance tests before changing to a regular expression
        form.

        Of course, if StartsWith is okay, that takes away the inefficiency
        anyway :)

        Jon

        Comment

        • =?ISO-8859-1?Q?G=F6ran_Andersson?=

          #5
          Re: comparison string object to string array...

          David Lazos wrote:
          Hi All,
          >
          I use Contains method of String object to determine if a string variable
          has another string, like that.
          *************** ************
          ipAddress.Conta ins("127.0.0")
          *************** *************
          >
          supposing that, there is a string array like
          >
          string[] aryIPAddress = {"127.0.0.", "192.168.1.","6 6.249.71."};
          >
          Is it possible to determine if any string in this array occurs in a String
          Object without using foreach or for patterns ?
          >
          Thanks in advance..
          >
          If the array is sorted (as in your example), you could use a binary
          search and a custom comparer, which would be considerably faster than
          looping through all the strings.

          Something like:

          if (Array.BinarySe arch(aryIPAddre ss, ip, new ContainsCompare r()) >= 0) {
          // ip address found
          }

          public class ContainsCompare r : IComparer<strin g{

          public int Compare(string x, string y) {
          if (x.Contains(y) /*or perhaps the other way around*/ ) {
          return 0;
          } else {
          return string.Compare( x, y);
          }
          }

          }

          --
          Göran Andersson
          _____
          Göran Anderssons privata hemsida.

          Comment

          • Pavel Minaev

            #6
            Re: comparison string object to string array...

            On Jul 12, 5:16 pm, "Jon Skeet [C# MVP]" <sk...@pobox.co mwrote:
            It will be somewhat faster, because it will reduce the list of
            candidate substrings as it matches - e.g. as soon as it sees that the
            first digit is "2", it will not even bother trying to match all IPs
            that start with anything else.
            >
            On the other hand, it has to join all the strings together to start
            with, escape them all, and then parse the generated regular
            expression.
            Oh yes, it largely depends on the specific use case. If those IPs come
            from some sort of a config file, and don't change at all (unless the
            user explicitly requests config reload, maybe), but are often matched
            against a large stream of IP addresses, then regex solution makes more
            sense, and then it is probably worth to compile the regex to IL as
            well - and this is the kind of scenario I had in mind (HTTP server
            matching IPs of incoming requests against preconfigured whitelist/
            blacklist which rarely changes, for example). If list of IP masks to
            match changes often, then the simple solution will likely be faster.

            Comment

            • Pavel Minaev

              #7
              Re: comparison string object to string array...

              On Jul 12, 8:53 pm, Göran Andersson <gu...@guffa.co mwrote:
              David Lazos wrote:
              Hi All,
              >
              I use Contains method of String object to determine if  a string variable
              has another string, like that.
              *************** ************
              ipAddress.Conta ins("127.0.0")
              *************** *************
              >
              supposing that,  there is a string array like
              >
              string[] aryIPAddress = {"127.0.0.", "192.168.1.","6 6.249.71."};
              >
              Is it possible to determine if any string in this array occurs in a String
              Object  without using foreach or for patterns ?
              >
              Thanks in advance..
              >
              If the array is sorted (as in your example), you could use a binary
              search and a custom comparer, which would be considerably faster than
              looping through all the strings.
              >
              Something like:
              >
              if (Array.BinarySe arch(aryIPAddre ss, ip, new ContainsCompare r()) >= 0) {
                 // ip address found
              >
              }
              >
              public class ContainsCompare r : IComparer<strin g{
              >
                 public int Compare(string x, string y) {
                   if (x.Contains(y) /*or perhaps the other way around*/ ) {
                     return 0;
                   } else {
                     return string.Compare( x, y);
                   }
                 }
              >
              }
              This won't work, because you'd have to have the array sorted using the
              same Comparer as well, and it does not provide a total ordering - for
              example, for a given pair of strings A="foobar", B="foo", this
              comparer can simultaneously say that A==B, and B<A. To illustrate,
              here's a sample set where it will go wrong:

              { "baz", "foo", "foobar" }

              A binary search for "bar" using the provided comparer would go like
              this:

              1. { "baz", "foo", "foobar" }. Pick middle element - "foo". Compare:
              "bar" < "foo". Take first half - { "baz" }
              2. { "baz" }. Pick middle element - "baz". Compare: "bar" < "baz".
              Take first half - { }.
              3. { }. Empty set, search unsuccessful.

              Whereas, obviously, "foobar" contains "bar", and a proper search would
              have found it.

              Comment

              • =?ISO-8859-1?Q?G=F6ran_Andersson?=

                #8
                Re: comparison string object to string array...

                Pavel Minaev wrote:
                On Jul 12, 8:53 pm, Göran Andersson <gu...@guffa.co mwrote:
                >David Lazos wrote:
                >>Hi All,
                >>I use Contains method of String object to determine if a string variable
                >>has another string, like that.
                >>************* **************
                >>ipAddress.Con tains("127.0.0" )
                >>************* ***************
                >>supposing that, there is a string array like
                >>string[] aryIPAddress = {"127.0.0.", "192.168.1.","6 6.249.71."};
                >>Is it possible to determine if any string in this array occurs in a String
                >>Object without using foreach or for patterns ?
                >>Thanks in advance..
                >If the array is sorted (as in your example), you could use a binary
                >search and a custom comparer, which would be considerably faster than
                >looping through all the strings.
                >>
                >Something like:
                >>
                >if (Array.BinarySe arch(aryIPAddre ss, ip, new ContainsCompare r()) >= 0) {
                > // ip address found
                >>
                >}
                >>
                >public class ContainsCompare r : IComparer<strin g{
                >>
                > public int Compare(string x, string y) {
                > if (x.Contains(y) /*or perhaps the other way around*/ ) {
                > return 0;
                > } else {
                > return string.Compare( x, y);
                > }
                > }
                >>
                >}
                >
                This won't work, because you'd have to have the array sorted using the
                same Comparer as well, and it does not provide a total ordering - for
                example, for a given pair of strings A="foobar", B="foo", this
                comparer can simultaneously say that A==B, and B<A. To illustrate,
                here's a sample set where it will go wrong:
                >
                { "baz", "foo", "foobar" }
                >
                A binary search for "bar" using the provided comparer would go like
                this:
                >
                1. { "baz", "foo", "foobar" }. Pick middle element - "foo". Compare:
                "bar" < "foo". Take first half - { "baz" }
                2. { "baz" }. Pick middle element - "baz". Compare: "bar" < "baz".
                Take first half - { }.
                3. { }. Empty set, search unsuccessful.
                >
                Whereas, obviously, "foobar" contains "bar", and a proper search would
                have found it.
                You are correct, it only works if the comparer uses StartsWith instead
                of Contains, which by the look of it might be what the OP is actually
                looking for.

                --
                Göran Andersson
                _____
                Göran Anderssons privata hemsida.

                Comment

                • =?ISO-8859-1?Q?G=F6ran_Andersson?=

                  #9
                  Re: comparison string object to string array...

                  David Lazos wrote:
                  Hi All,
                  >
                  I use Contains method of String object to determine if a string variable
                  has another string, like that.
                  *************** ************
                  ipAddress.Conta ins("127.0.0")
                  *************** *************
                  >
                  supposing that, there is a string array like
                  >
                  string[] aryIPAddress = {"127.0.0.", "192.168.1.","6 6.249.71."};
                  >
                  Is it possible to determine if any string in this array occurs in a String
                  Object without using foreach or for patterns ?
                  >
                  Thanks in advance..
                  >
                  Another alternative is to not compare strings at all.

                  Create an IpRange class that has an upper and lower limit for an ip
                  range, e.g. 127.0.0.0 - 127.0.0.255. An ip address (at least in ip4) can
                  be represented as an uint, so checking if an ip address is within the
                  range would be two integer comparisons. Much more efficient than
                  comparing strings.

                  --
                  Göran Andersson
                  _____
                  Göran Anderssons privata hemsida.

                  Comment

                  Working...