I want to get the string representation of a lambda Func<> Expression to get the Property Path. I have this example
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses["Address"];
and i am expecting a string
"EmployeeInfo.Addresses["Address"]"
when i do _xxx.ToString(); i'll just do some string parsing and i can get the result above.
My problem is when i do
var _addrName = "Address";
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses[_addrName];
i got a very long string
"EmployeeInfo.Addresses.get_Item(value(UnitTestProj.UnitTest.AnyTest+<>c__DisplayClass0)._addr)"
which is very hard to manipulate to come up with
"EmployeeInfo.Addresses["Address"]"
Is there any way to achieve my purpose?
TIA
This should get you pretty far - it's very hacky but I don't think there's a way around it:
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses[address];
WriteLine(ExprToString(_xxx)); //e.EmployeeInfo.Addresses[address]
_xxx = x => x.EmployeeInfo.Addresses["XYZ"];
WriteLine(ExprToString(_xxx)); //x.EmployeeInfo.Addresses["XYZ"]
_xxx = y => y.EmployeeInfo.Addresses[null];
WriteLine(ExprToString(_xxx)); //y.EmployeeInfo.Addresses[null]
_xxx = z => z.EmployeeInfo.Name;
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Name
_xxx = z => z.EmployeeInfo.GetSalary();
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.GetSalary()
_xxx = z => z.EmployeeInfo.Addresses.Select(a => a.Street);
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Addresses.Select(a.Street)
_xxx = z => z.EmployeeInfo.Array[3];
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Array[3]
The implementation:
static string ExprToString(Expression expr)
{
switch (expr.NodeType)
{
case ExpressionType.Lambda:
//x => (Something), return only (Something), the Body
return ExprToString(((LambdaExpression) expr).Body);
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
//type casts are not important
return ExprToString(((UnaryExpression) expr).Operand);
case ExpressionType.Call:
//method call can be an Indexer (get_Item),
var callExpr = (MethodCallExpression) expr;
if (callExpr.Method.Name == "get_Item")
{
//indexer call
return ExprToString(callExpr.Object) + "[" + string.Join(",", callExpr.Arguments.Select(ExprToString)) + "]";
}
else
{
//method call
var arguments = callExpr.Arguments.Select(ExprToString).ToArray();
string target;
if (callExpr.Method.IsDefined(typeof (ExtensionAttribute), false))
{
//extension method
target = string.Join(".", arguments[0], callExpr.Method.Name);
arguments = arguments.Skip(1).ToArray();
}
else if (callExpr.Object == null)
{
//static method
target = callExpr.Method.Name;
}
else
{
//instance method
target = string.Join(".", ExprToString(callExpr.Object), callExpr.Method.Name);
}
return target + "(" + string.Join(",", arguments) + ")";
}
case ExpressionType.MemberAccess:
//property or field access
var memberExpr = (MemberExpression) expr;
if (memberExpr.Expression.Type.Name.Contains("<>")) //closure type, don't show it.
{
return memberExpr.Member.Name;
}
else
{
return string.Join(".", ExprToString(memberExpr.Expression), memberExpr.Member.Name);
}
}
//by default, show the standard implementation
return expr.ToString();
}
Related
I need to validate password entered by user and check if the password contains at least one uppercase and one lowercase char in Dart.
I wrote this String extension:
extension StringValidators on String {
bool containsUppercase() {
// What code should be here?
}
bool containsLowercase() {
// What code should be here?
}
}
And use it like this:
final text = passwordTextController.text;
final isValid = text.containsUppercase() && text.containsLowercase();
Is there any regexp for this purpose? Or it should be plain algorithm? Please help me to find out the elegant way. Thanks!
Minimum 1 Upper case,
Minimum 1 lowercase,
Minimum 1 Numeric Number,
Minimum 1 Special Character,
Common Allow Character ( ! # # $ & * ~ )
bool validateStructure(String value){
String pattern = r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!##\$&*~]).{8,}$';
RegExp regExp = new RegExp(pattern);
return regExp.hasMatch(value);
}
extension StringValidators on String {
bool get containsUppercase => contains(RegExp(r'[A-Z]'));
bool get containsLowercase => contains(RegExp(r'[a-z]'));
}
For only minimum 1 upper and minimum 1 Lower only, you could use this RegEx:
RegExp regEx = new RegExp(r"(?=.*[a-z])(?=.*[A-Z])\w+");
String a = "aBc";
String b = "abc";
String c = "ABC";
print("a => " + regEx.hasMatch(a).toString());
print("b => " + regEx.hasMatch(b).toString());
print("c => " + regEx.hasMatch(c).toString());
Expected Result:
I/flutter (10220): a => true
I/flutter (10220): b => false
I/flutter (10220): c => false
Reusable
extension StringValidators on String {
meetsPasswordRequirements() {
RegExp regEx = new RegExp(r"(?=.*[a-z])(?=.*[A-Z])\w+");
return regEx.hasMatch(this);
}
}
Use
final isValid = text.meetsPasswordRequirements();
void main() {
solve("coDE");
}
String solve(String s) {
// your code here
List _a = s.split("");
String _b = "";
List _x = [];
List _y = [];
for(var i in _a){
if(i.toString() == i.toString().toUpperCase()){
_x.add(i);
}else{
_y.add(i);
}
}
if(_x.length == _y.length){
_b = _a.join().toLowerCase();
}else if(_x.length > _y.length){
_b = _a.join().toUpperCase();
}else if(_x.length < _y.length){
_b = _a.join().toLowerCase();
}
return "$_b";
}
OR
String solve2(String str) {
return RegExp(r'[A-Z]').allMatches(str).length >
RegExp(r'[a-z]').allMatches(str).length
? str.toUpperCase()
: str.toLowerCase();
}
Is it possible to change the default option all column filters? I'm pretty sure I can accomplish this with some JavaScript, but I'd like to know if there's any way within the Acumatica framework to change this.
The answer will be no. The filter is inside the PX.Web.UI.dll in the PXGridFilter class which is an internal class. The property that you are interested in is the Condition.
The value is set inside one of the private methods of the PXGrid class. The code of the method is below:
private IEnumerable<PXGridFilter> ab()
{
List<PXGridFilter> list = new List<PXGridFilter>();
if (this.FilterID != null)
{
Guid? filterID = this.FilterID;
Guid guid = PXGrid.k;
if (filterID == null || (filterID != null && filterID.GetValueOrDefault() != guid))
{
using (IEnumerator<PXResult<FilterRow>> enumerator = PXSelectBase<FilterRow, PXSelect<FilterRow, Where<FilterRow.filterID, Equal<Required<FilterRow.filterID>>, And<FilterRow.isUsed, Equal<True>>>>.Config>.Select(this.DataGraph, new object[]
{
this.FilterID.Value
}).GetEnumerator())
{
while (enumerator.MoveNext())
{
FilterRow row = enumerator.Current;
string dataField = row.DataField;
PXCache pxcache = PXFilterDetailView.TargetCache(this.DataGraph, new Guid?(this.FilterID.Value), ref dataField);
if (this.Columns[row.DataField] != null)
{
List<PXGridFilter> list2 = list;
int valueOrDefault = row.OpenBrackets.GetValueOrDefault();
string dataField2 = row.DataField;
string dataField3 = row.DataField;
int value = (int)row.Condition.Value;
object value2 = pxcache.ValueFromString(dataField, row.ValueSt);
string valueText = row.ValueSt.With((string _) => this.Columns[row.DataField].FormatValue(_));
object value3 = pxcache.ValueFromString(dataField, row.ValueSt2);
string value2Text = row.ValueSt2.With((string _) => this.Columns[row.DataField].FormatValue(_));
int valueOrDefault2 = row.CloseBrackets.GetValueOrDefault();
int? #operator = row.Operator;
int num = 1;
list2.Add(new PXGridFilter(valueOrDefault, dataField2, dataField3, value, value2, valueText, value3, value2Text, valueOrDefault2, #operator.GetValueOrDefault() == num & #operator != null));
}
}
return list;
}
}
}
if (this.FilterRows != null && this.FilterRows.Count > 0)
{
for (int i = 0; i < this.FilterRows.Count; i++)
{
PXFilterRow row = this.FilterRows[i];
list.Add(new PXGridFilter(row.OpenBrackets, row.DataField, row.DataField, (int)row.Condition, row.Value, row.Value.With(delegate(object _)
{
if (this.Columns[row.DataField] == null)
{
return _.ToString();
}
return this.Columns[row.DataField].FormatValue(_);
}), row.Value2, row.Value2.With(delegate(object _)
{
if (this.Columns[row.DataField] == null)
{
return _.ToString();
}
return this.Columns[row.DataField].FormatValue(_);
}), row.CloseBrackets, row.OrOperator));
}
}
return list;
}
UPDATE
The below JS code allows you to change the condition of the last set filter:
px_all.ctl00_phG_grid_fd.show();
px_all.ctl00_phG_grid_fd_cond.items.items[7].setChecked(true);
px_all.ctl00_phG_grid_fd_ok.element.click();
px_all.ctl00_phG_grid_fd_cond.items.items[7].value "EQ"
px_all.ctl00_phG_grid_fd_cond.items.items[8].value "NE"
px_all.ctl00_phG_grid_fd_cond.items.items[9].value "GT"
px_all.ctl00_phG_grid_fd_cond.items.items[13].value "LIKE"
px_all.ctl00_phG_grid_fd_cond.items.items[14].value "LLIKE"
px_all.ctl00_phG_grid_fd_cond.items.items[15].value "RLIKE"
px_all.ctl00_phG_grid_fd_cond.items.items[16].value "NOTLIKE"
px_all.ctl00_phG_grid_fd_cond.items.items[18].value "ISNULL"
px_all.ctl00_phG_grid_fd_cond.items.items[19].value "ISNOTNULL"
I have the following code:
def foo(str: String, key: Char) : String = {
breakable{
for(it <- 0 until str.length){
if(str.charAt(it) != key){
str.slice(0, it) + str.slice(it+1, str.length)
break
}
}
}
str
}
However, str.slice(0, it) + str.slice(it+1, str.length) is never returned, only str.
Does anyone know how I can fix this?
It has to be done in two parts. First you find the index of this char in string (if it exists). Now, if you find the index, you return the sliced string otherwise return the original string.
I am assuming you can not use some of the String methods to directly do this...
If you are using Scala 2.13
def foo(string: String, key: Char): String = {
val indexOption =
string
.lazyZip(LazyList.from(0))
.find({ case (c, i) => c == key })
.map({ case (c, i) => i })
indexOption
.map(index => string.slice(0, index) + string.slice(index + 1, string.length))
.getOrElse(string)
}
Or, if you are using Scala 2.12,
def foo(string: String, key: Char): String = {
val indexOption =
string
.toStream
.zipWithIndex
.find({ case (c, i) => c == key })
.map({ case (c, i) => i })
indexOption
.map(index => string.slice(0, index) + string.slice(index + 1, string.length))
.getOrElse(string)
}
The str is a val and it is not updated in your operations... your are ignoring the result of that string addition
pretty much your code is exactly the same as:
def foo(str: String, key: Char) : String = str
try using a var if you want to keep updating the result, or use other methods over the string to achieve the same without var... with the var it could be something like this:
import util.control.Breaks._
def foo(str: String, key: Char) : String = {
var bar = str
breakable {
for(it <- 0 until str.length){
if(str.charAt(it) != key){
bar = str.slice(0, it) + str.slice(it+1, str.length)
break
}
}
}
bar
}
edit:
As you commented you must not use var on your assignment, consider the foldLeft to sort out the same problem:
def foo(str: String, key: Char): String = {
string
.foldLeft("") {
case (acc, c) =>
if(c == key) acc
else acc + c
}
}
<ReflectionTest>(x => x.ReflectionTestHelperClass1.ReflectionTestHelperClass2.InnerField)
When I am passing this expression, I want return "ReflectionTestHelperClass1.ReflectionTestHelperClass2.InnerField" as a string.
Can anybody help me?
(x => x.ReflectionTestHelperClass1.ReflectionTestHelperClass2.InnerField), this is Expression type you can use this expression to get string as you required.
public string GetExpresionBody(Expression expression)
{
var memberExpression = expression as MemberExpression;
if (memberExpression == null)
return string.Empty;
if (memberExpression.NodeType == ExpressionType.Parameter)
return string.Empty;
var classValue = GetExpresionBody(memberExpression.Expression);
var result = classValue + (string.IsNullOrWhiteSpace(classValue) ? "" : ".") + memberExpression.Member.Name;
return result;
}
try this...
private static string GetExpresion(Expression expression)
{
var memberExpression = expression as MemberExpression;
if (memberExpression == null)
return string.Empty;
if (memberExpression.NodeType == ExpressionType.Parameter)
return string.Empty;
var result = GetExpresion(memberExpression.Expression) + memberExpression.Member.Name;
// remove '.' from result which is comes first
return result;
}
I have a problem in which I have to SWAP or move characters and integers. Like I have any characters A . now I have some cases, like
NOTE:- Have to use characters A-Z and integers 0-9
A, now I want that when my program run I assign some integer value to this character, If I assign value 3 to this character then A will become D or it just move to 3 places.
Now if I have a character like Y and I add 4 then it will become C means after Z it will again start from character A.
Same condition I have to follow with Integer if i have 9 and we assign 3 to it then it will become 2 because loop start from 0 not from 1. Means we have to use only 0-9 integers.
I know that i am using wrong name to question but i have no idea that what lines i have to use for that kind of question.
Hope you understand my problem.
Thanks in advance.
Try the below extension method, which does the following:
It creates 2 dictionaries in order to speed up the key look up in the alphabet
Will parse the inputString variable, split it in substrings of the length of the moveString variable's length (or the remainder)
On every substring, it will evaluate each character in order to detect if it's a digit
If it's not a digit, it looks up for the value in the swappedAlphabet dictionary, by using the int key
If it's a digit, it applies a modulo operation on the sum of the digit and the corresponding moveint value
It finally aggregates all the characters in the final result string
Here's the code:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
string
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string inputString = "ABC123D", moveString = "12";
var result = inputString.Swap(alphabet, moveString);
Console.WriteLine(result);
}
}
static class ExtensionMethods
{
public static Dictionary<TValue, TKey>
SwapKeysValues<TKey, TValue>(this Dictionary<TKey, TValue> input)
{
var result = new Dictionary<TValue, TKey>();
input.ToList().ForEach((keyValuePair) =>
{
result.Add(keyValuePair.Value, keyValuePair.Key);
});
return result;
}
public static string Swap(
this string input,
string alphabet,
string move)
{
Dictionary<char, int>
alphabetDictionary = new Dictionary<char, int>();
for (int i = 0; i < alphabet.Length; i++)
{
alphabetDictionary.Add(alphabet[i], i);
}
var swapedAlphabet = alphabetDictionary.SwapKeysValues();
return Enumerable
.Range(0, (int)Math.Ceiling(input.Length / (move.Length * 1M)))
.ToList()
.Aggregate<int, string>("", (s, i) =>
{
var l = i * move.Length + move.Length;
var cInput = input.Substring(i * move.Length,
(l > input.Length)
? input.Length - i * move.Length : move.Length);
return s + cInput
.Select((c, index) =>
{
int intCandidate;
if (!Int32.TryParse(c.ToString(), out intCandidate))
{
var length = (alphabetDictionary[c] +
Int32.Parse(move[index].ToString()));
return
swapedAlphabet[(alphabet.Length > length)
? length : length % alphabet.Length];
}
else
{
var moveInt = Int32.Parse(move[index].ToString());
return Char.Parse(((intCandidate + moveInt) % 10)
.ToString());
}
})
.Aggregate<char, string>("", (a, b) => a + b);
});
}
}
Another alternative you have is relying on the in-built character/integer types which follow the order you want; with an additional consideration: if you account for caps, it would deliver caps ("B" after "A" and "b" after "a"). The only thing you need to worry about is making sure that the iterations will be limited to the A-Z/0-9 boundaries. Sample code:
public string moveChar(string inputChar, int noPos)
{
string outChar = checkBoundaries(inputChar, noPos);
if (outChar == "")
{
outChar = basicConversion(inputChar, noPos);
}
return outChar;
}
public string basicConversion(string inputChar, int noPos)
{
return Convert.ToString(Convert.ToChar(Convert.ToInt32(Convert.ToChar(inputChar)) + noPos));
}
public string checkBoundaries(string inputChar, int noPos)
{
string outString = "";
int count1 = 0;
do
{
count1 = count1 + 1;
string curTemp = basicConversion(inputChar, 1);
if (inputChar.ToLower() == "z" || curTemp.ToLower() == "z")
{
if (inputChar.ToLower() != "z")
{
noPos = noPos - count1;
}
inputChar = "a";
outString = "a";
if (inputChar == "Z" || curTemp == "Z")
{
inputChar = "A";
outString = "A";
}
count1 = 1;
}
else if (inputChar == "9" || curTemp == "9")
{
if (inputChar != "9")
{
noPos = noPos - count1;
}
inputChar = "0";
outString = "0";
count1 = 1;
}
else
{
inputChar = curTemp;
outString = inputChar;
}
} while (count1 < noPos);
return outString;
}
It expects strings (just one character (letter or number) per call) and you can call it simply by using: moveChar("current letter or number", no_of_pos_to_move). This version accounts just for "positive"/"forwards" movements but it might easily be edited to account for the inverse situation.
Here's a very simple way to implement a Caesar Cipher with the restrictions you defined.
var shift = 3;
var input = "HELLO WORLD 678";
var classAlphabets = new Dictionary<UnicodeCategory, string>
{
{ UnicodeCategory.SpaceSeparator, " " },
{ UnicodeCategory.UppercaseLetter, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" },
{ UnicodeCategory.DecimalDigitNumber, "0123456789" }
};
var encoded = input.ToUpperInvariant()
.Select(c => new { Alphabet = classAlphabets[Char.GetUnicodeCategory(c)], Character = c })
.Select(x => new { x.Alphabet, Index = x.Alphabet.IndexOf(x.Character) })
.Select(x => new { x.Alphabet, Index = x.Index + shift })
.Select(x => new { x.Alphabet, Index = x.Index % x.Alphabet.Length })
.Select(x => x.Alphabet.ElementAt(x.Index))
.Aggregate(new StringBuilder(), (builder, character) => builder.Append(character))
.ToString();
Console.Write(encoded);
// encoded = "KHOOR ZRUOG 901"
Decoding is simply a case of inverting the shift.
Caesar cipher can be easier like this:
static char Encrypt(char ch, int code)
{
if (!char.IsLetter(ch))
{
return ch;
}
char offset = char.IsUpper(ch) ? 'A' : 'a';
return (char)(((ch + code - offset) % 26) + offset);
}
static string Encrypt(string input, int code)
{
return new string(input.ToCharArray().Select(ch => Encrypt(ch, code)).ToArray());
}
static string Decrypt(string input, int code)
{
return Encrypt(input, 26 - code);
}
const string TestCase = "Pack my box with five dozen liquor jugs.";
static void Main()
{
string str = TestCase;
Console.WriteLine(str);
str = Encrypt(str, 5);
Console.WriteLine("Encrypted: {0}", str);
str = Decrypt(str, 5);
Console.WriteLine("Decrypted: {0}", str);
Console.ReadKey();
}