cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Browse apps to extend the software in the new JMP Marketplace
Choose Language Hide Translation Bar
Voizingu
Level III

Remove element from a list that contain elements from a second list in JSL

Hello,

 

Removing elements from a list is well documented in the the JSL discussions but for some reason I cannot figure out how to do this:

I need to remove elements from a list if the elements CONTAIN string from another list (not exact match).

 

Example below: I am trying to remove all elements that contain "Cal" or "Blue"

 

Thanks in advance,

 

-Voiz

Names Default To Here( 1 );
clear symbols();
Deletesymbols();

ChosenDataCol = {"Cal1", "Cal2", "Cal3", "Temp1", "Temp25", "Blue56", "Blue32", "Blue95"};

RemoveCol = {"Cal", "Blue"};

For (i=1,i<=N Items( RemoveCol ), i++,
	For (j=N Items (ChosenDataCol), j<=1, j--,
		If(contains(ChosenDataCol[j], Eval(RemoveCol[i]))==1, 
			Remove from(ChosenDataCol, j)
		)
	)
);

show (ChosenDataCol);

 

2 ACCEPTED SOLUTIONS

Accepted Solutions
jthi
Super User

Re: Remove element from a list that contain elements from a second list in JSL

You can also utilize For Each or Filter Each

Names Default To Here(1);

ChosenDataCol = {"Cal1", "Cal2", "Cal3", "Temp1", "Temp25", "Blue56", "Blue32", "Blue95"};
RemoveCol = {"Cal", "Blue"};

vals = Filter Each({val1}, ChosenDataCol,
	res = Filter Each({val2}, RemoveCol,
		!Contains(val1, val2)
	);
	N Items(res) == N Items(RemoveCol);
);

// ChosenDataCol = vals; // {"Temp1", "Temp25"}
-Jarmo

View solution in original post

jthi
Super User

Re: Remove element from a list that contain elements from a second list in JSL

You will also have to consider what N Items(res) == N Items(KeepCol); is doing. You can add extra print inside the loop to assist in figuring that out

Names Default To Here(1);

ChosenDataCol = {"SiCal 1", "Ba Cal 2", "toCal 3", "Si Temp1", "bouTemp25", "CaBlue 56", "SiBlue 32", "Blue 95"};
KeepCol = {"Cal", "Blue"};

vals = Filter Each({val1}, ChosenDataCol,
	res = Filter Each({val2}, KeepCol,
		Contains(val1, val2)
	);
	show(res);
	N Items(res) != N Items(KeepCol);
);

Also if you can have situations where both Cal and Blue can appear in single string, you will need to utilize a bit different method

-Jarmo

View solution in original post

7 REPLIES 7
txnelson
Super User

Re: Remove element from a list that contain elements from a second list in JSL

In your For() loop, 

j<=1

should be

j>=1
Names Default To Here( 1 );
clear symbols();
Deletesymbols();

ChosenDataCol = {"Cal1", "Cal2", "Cal3", "Temp1", "Temp25", "Blue56", "Blue32", "Blue95"};

RemoveCol = {"Cal", "Blue"};

For (i=1,i<=N Items( RemoveCol ), i++,
	For (j=N Items (ChosenDataCol), j>=1, j--,
		If(contains(ChosenDataCol[j], RemoveCol[i])==1, 
			Remove from(ChosenDataCol, j)
		)
	)
);
show (ChosenDataCol);
Jim
Voizingu
Level III

Re: Remove element from a list that contain elements from a second list in JSL

Hi Jim,

 

Ha yes, I missed that

The solution works BUT it seems that the contains() is not very robust: if the String to look is in the middle of the list element, it doesn't find it. 

Do you know why?

The log of the script below gives:

ChosenDataCol = {"Si Cal 1", "Ba Cal 2", "toCal 3", "Temp 1", "Temp 25", "SiBlue 32"};

instead of 

ChosenDataCol = {"Temp 1", "Temp 25"};

 

Names Default To Here( 1 );
clear symbols();
Deletesymbols();

ChosenDataCol = {"Si Cal 1", "Ba Cal 2", "toCal 3", "Temp 1", "Temp 25", "Blue 56", "SiBlue 32", "Blue 95"};

RemoveCol = {"Cal", "Blue"};

For (i=1,i<=N Items( RemoveCol ), i++,
	For (j=N Items (ChosenDataCol), j>=1, j--,
		If(contains(ChosenDataCol[j], Eval(RemoveCol[i]))==1, 
			Remove from(ChosenDataCol, j)
		)
	)
);

show (ChosenDataCol);

Thanks 

txnelson
Super User

Re: Remove element from a list that contain elements from a second list in JSL

Please refer to my initial response JSL.  

Contains( ChosenDataCol[j], Eval( RemoveCol[i] ) ) == 1

was changed to

contains(ChosenDataCol[j], RemoveCol[i])==1

which allows for the correct answer.  I am not sure why the Eval() is interfering with the Contains()

Jim
jthi
Super User

Re: Remove element from a list that contain elements from a second list in JSL

You can also utilize For Each or Filter Each

Names Default To Here(1);

ChosenDataCol = {"Cal1", "Cal2", "Cal3", "Temp1", "Temp25", "Blue56", "Blue32", "Blue95"};
RemoveCol = {"Cal", "Blue"};

vals = Filter Each({val1}, ChosenDataCol,
	res = Filter Each({val2}, RemoveCol,
		!Contains(val1, val2)
	);
	N Items(res) == N Items(RemoveCol);
);

// ChosenDataCol = vals; // {"Temp1", "Temp25"}
-Jarmo
Voizingu
Level III

Re: Remove element from a list that contain elements from a second list in JSL

Hello Jarmo,

 

Thanks the Filter each () seems to do the trick, even with more intricate inputs (see below).

Ideally I need the options to filter ChosenDataCol with the 2 ways:

- Remove unwanted elements based on list of string (this method here, which works now) => RemoveCol

- Only keep elements based on list of string (the opposite of the method here)

 

I thought removing the "NOT" from "!Contains()" should do the trick but it returns an empty list { }.

 

Do you know why?

 

thanks 

 

Remove elements <-- works well

Names Default To Here(1);

ChosenDataCol = {"SiCal 1", "Ba Cal 2", "toCal 3", "Si Temp1", "bouTemp25", "CaBlue 56", "SiBlue 32", "Blue 95"};
RemoveCol = {"Cal", "Blue"};

vals = Filter Each({val1}, ChosenDataCol,
	res = Filter Each({val2}, RemoveCol,
		!Contains(val1, val2)
	);
	N Items(res) == N Items(RemoveCol);
);

// log : {"Si Temp1", "bouTemp25"}

Keep elements <-- doesn't work

Names Default To Here(1);

ChosenDataCol = {"SiCal 1", "Ba Cal 2", "toCal 3", "Si Temp1", "bouTemp25", "CaBlue 56", "SiBlue 32", "Blue 95"};
KeepCol = {"Cal", "Blue"};

vals = Filter Each({val1}, ChosenDataCol,
	res = Filter Each({val2}, KeepCol,
		Contains(val1, val2)
	);
	N Items(res) == N Items(KeepCol);
);

// log : {}

 

jthi
Super User

Re: Remove element from a list that contain elements from a second list in JSL

You will also have to consider what N Items(res) == N Items(KeepCol); is doing. You can add extra print inside the loop to assist in figuring that out

Names Default To Here(1);

ChosenDataCol = {"SiCal 1", "Ba Cal 2", "toCal 3", "Si Temp1", "bouTemp25", "CaBlue 56", "SiBlue 32", "Blue 95"};
KeepCol = {"Cal", "Blue"};

vals = Filter Each({val1}, ChosenDataCol,
	res = Filter Each({val2}, KeepCol,
		Contains(val1, val2)
	);
	show(res);
	N Items(res) != N Items(KeepCol);
);

Also if you can have situations where both Cal and Blue can appear in single string, you will need to utilize a bit different method

-Jarmo
Voizingu
Level III

Re: Remove element from a list that contain elements from a second list in JSL

Hello Jarmo,

 

The "show(res)" helped me understand the logic. I really have to use For Each () functions more

there was a missing "!" before Contains to make the script really work, but now my 2 functions work properly.

I will have to think about your last remark, not sure if that scenario exists!

 

Thanks again  

 

Voiz

 

Names Default To Here(1);

ChosenDataCol = {"SiCal 1", "Ba Cal 2", "toCal 3", "Si Temp1", "bouTemp25", "CaBlue 56", "SiBlue 32", "Blue 95"};
KeepCol = {"Cal", "Blue"};

vals = Filter Each({val1}, ChosenDataCol,
	res = Filter Each({val2}, KeepCol,
		!Contains(val1, val2)
	);
	N Items(res) != N Items(KeepCol);
);

show(vals)

// vals = {"SiCal 1", "Ba Cal 2", "toCal 3", "CaBlue 56", "SiBlue 32", "Blue 95"};