user1531040
user1531040

Reputation: 2291

How to find if a string exists only with numbers? (in LINQ)

I have a LINQ query and I want to have addresses between a range of zipcodes from 1000 to 2000.

How do I find if the zipcode with a value "3456 AB" (I only check the 4 first characters) exists of only digits?

var address = address.Where(p => p.Zipcode != null
                              && p.Zipcode.Length > 4 
                              && p.Zipcode.Substring(0, 4).Isnumber() 
                              && Convert.ToInt32(p.Zipcode.Substring(0, 4)) > zipcodeFrom);

Upvotes: 1

Views: 3098

Answers (7)

Robert Synoradzki
Robert Synoradzki

Reputation: 2036

You should just use TryParse, it returns bool if the string is convertable to an int.

Some dummy data to test on:

var addresses = new[]
{
    new { Zipcode = "3456 AB" }, // These of course have other fields,
    new { Zipcode = "345678"  }, // but in this example we only care
    new { Zipcode = "876543"  }, // about Zipcode
    new { Zipcode = "X3456"   },
    new { Zipcode = "5000 GG" },
};

The query:

    int zipcodeFrom = 4000;
    int parsedZipcode;

    var qualifiedAddresses = addresses
        .Where(p => true
            && p.Zipcode != null
            && p.Zipcode.Length >= 4
            && int.TryParse(p.Zipcode.Substring(0, 4), out parsedZipcode)
            && parsedZipcode > zipcodeFrom
        );

Output:

876543 
5000 GG 

Upvotes: 2

user1531040
user1531040

Reputation: 2291

Thank you for all your answers. I have tried it all.

Maybe it's LINQ-to-SQL. But all functions as All, char.IsDigit and Regex.Match doesn't work. The "table" from SQL Server was a view. So I changed the view for an extra field ZipcodeInt.

var address = address.Where(p => p.Zipcode != null
                                && p.Zipcode.Length > 4 
                                && p.ZipcodeInt > zipcodeFrom);

Upvotes: 0

user6996876
user6996876

Reputation:

You can match a 4 digits string and parse it.

var resultString = int.Parse(
    Regex.Match(zip, @"\d{4}").Value
    );

If you want the Linq equivalent

var linqEquiv = zip.Select((c, i) =>
  String.Join("",zip.Skip(i).Take(4))).FirstOrDefault(zip => 
    { int i; return int.TryParse(zip, out i) && i >= 1000 && i <= 2000 ; });

Finally, with your class definition

var linqEquivalent = address.Where(a => a.ZipCode.ToArray().Select((c, i) =>
    String.Join("", a.ZipCode.ToArray().Skip(i).Take(4))).FirstOrDefault(zip =>
        { int i; return int.TryParse(zip, out i) && i >= 1000 && i <= 2000; }) != null);

test case

with the following list

var address = new List<Address>() {
    new Address() { ZipCode = "123 cap 1567 AB 6666" }, // 1567 matches conds
    new Address() { ZipCode = "123 cap 4567 AB 6666" },
    new Address() { ZipCode = "123 cap 4567 AB 1666" } }; // 1666 matches conds

linqEquivalent will contain the first and the third address.

Upvotes: 1

TVOHM
TVOHM

Reputation: 2742

var valid = addresses
    .Where(a => 
        a.Zipcode != null 
        && a.Zipcode.Length > 4 
        && a.Zipcode.Substring(0, 4).All(char.IsDigit))
    .Select(a => new { Address = a, Zipcode = Convert.ToInt32(a.Zipcode.Substring(0, 4)) })
    .Where(a => a.Zipcode >= 1000 && a.Zipcode <= 2000)
    .Select(a => a.Address);

Keeping your original checks in - firstly we filter out all addresses where Zipcode is null, is less than 4 in length, or the first 4 characters are not all digits.

The we project a new sequence of an anonymous type containing the address and the 4 digit Zipcode as an int. We can then filter this collection by checking if the int Zipcode is within the range we require. Finally we return the original addresses.

Upvotes: 1

Dmitry Egorov
Dmitry Egorov

Reputation: 9650

You may use Regex to check if the first four chars represent a number from 1000 to 2000. This would simplify your expression significantly:

var address = address.Where(p => p.Zipcode != null
    && Regex.Match(p.Zipcode, @"^[12]\d{3}").Success);

Upvotes: 3

kgzdev
kgzdev

Reputation: 2885

int intzipcode;

var address = address
    .Where(p => true
        && p.Zipcode != null
        && p.Zipcode.Length > 4
        && int.TryParse(p.Zipcode.Substring(0, 4), out intzipcode)
        && Convert.ToInt32(p.Zipcode.Substring(0, 4)) > 1000
        && Convert.ToInt32(p.Zipcode.Substring(0, 4)) < 2000
    )

Upvotes: 0

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37000

For example:

var valid = adress.Where(x => x.ZipCode != null)
    .Select(x => x.ZipCode)
    .Where(x => x.Take(4).All(Char.IsDigit));

The Where-clause checks the four first characters of every ZipCode to be all numbers. Be aware that when using Take(4) you will get an enumeration of type char, not just a string. Thus you can simply call x.IsDigit to check if the character represents a number.

Upvotes: 1

Related Questions