简化条件语句[Perl]

时间:2017-02-04 09:50:04

标签: perl if-statement multidimensional-array

我有一个3d矩阵,我需要检查几个元素是否等于一个值(未来每个元素的目标值可能不同)。

有没有办法在最后简化if条件?我希望有一些方法来设置'条件'矩阵并比较它们,同时忽略在条件无关紧要的元素。

任何提示?

目前我的代码是:

use warnings;
use strict;

#fancy matrix
my @matrix; 

#set to a blank 3d test matrix
for my $i (0 .. 6) {
    for my $j (0 .. 6) {
        for my $k  (0 .. 2) {
            $matrix[$i][$j][$k] = 0;
        }
    }
}

#set some values for matrix

for my $j (0..2, 4..6) {
    my $i = 4;
    for my $k  (0 .. 2) {
        $matrix[$i][$j][$k] = 1;
    }
}
for my $i (0..2, 4..6) {
    my $j = 4;
    for my $k  (0 .. 2) {
        $matrix[$i][$j][$k] = 1;
    }
}

#the conditional problem child
if ($matrix[0][4][0] == 1 and $matrix[0][4][1] == 1 and $matrix[0][4][2] == 1 and $matrix[1][4][0] == 1 and $matrix[1][4][1] == 1 and $matrix[1][4][2] == 1 and $matrix[2][4][0] == 1 and $matrix[2][4][1] == 1 and $matrix[2][4][2] == 1 and $matrix[4][4][0] == 1 and $matrix[4][4][1] == 1 and $matrix[4][4][2] == 1 and $matrix[5][4][0] == 1 and $matrix[5][4][1] == 1 and $matrix[5][4][2] == 1 and $matrix[6][4][0] == 1 and $matrix[6][4][1] == 1 and $matrix[6][4][2] == 1 and $matrix[4][0][0] == 1 and $matrix[4][0][1] == 1 and $matrix[4][0][2] == 1 and $matrix[4][1][0] == 1 and $matrix[4][1][1] == 1 and $matrix[4][1][2] == 1 and $matrix[4][2][0] == 1 and $matrix[4][2][1] == 1 and $matrix[4][2][2] == 1 and $matrix[4][4][0] == 1 and $matrix[4][4][1] == 1 and $matrix[4][4][2] == 1 and $matrix[4][5][0] == 1 and $matrix[4][5][1] == 1 and $matrix[4][5][2] == 1 and $matrix[4][6][0] == 1 and $matrix[4][6][1] == 1 and $matrix[4][6][2] == 1) {
    print "it worked";
}

<stdin>;

编辑注意:如果我接近它的方式是最好的(怀疑它),是否至少有一种方法可以使if条件可读(不是36在单行上进行比较)?

3 个答案:

答案 0 :(得分:2)

使更具可读性(但速度不快)的一种方法是使用Test::Deep's Test::Deep::NoTest中的eq_deeply

你传递了两个数据结构,它告诉你它们是否相等。如果你只知道结构的一半,你可以使用漂亮的辅助函数来忽略它的一部分。

use Test::Deep::NoTest;

my $equal = eq_deeply( $matrix,
    [
        [
            [ 1, 0, ],
            [ 0, 0, ],
        ],
        [
            [ 1, 1, ],
            [ 0, 1, ],
        ],
        [
            [ 1, 1, ],
            [ 0, 1, ],
        ],
    ]
);

if ($equal) {
    # ...
}

答案 1 :(得分:1)

我建议您构建一个对子集中所有矩阵元素的引用数组。然后,您可以在简单的package com.secrethq.ads; import java.lang.ref.WeakReference; import org.cocos2dx.lib.Cocos2dxActivity; import android.util.Log; import android.view.View; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.RelativeLayout; import com.seth.slex.show.PTPlayer; import com.seth.slex.show.R; import com.google.android.gms.ads.*; public class PTAdAdMobBridge { private static final String TAG = "PTAdAdMobBridge"; private static Cocos2dxActivity activity; private static WeakReference<Cocos2dxActivity> s_activity; private static AdView adView; private static InterstitialAd interstitial; private static LinearLayout layout; private static boolean isScheduledForShow; private static native void interstitialDidFail(); private static native void bannerDidFail(); public static void initBridge(Cocos2dxActivity activity){ Log.v(TAG, "PTAdAdMobBridge -- INIT"); isScheduledForShow = false; PTAdAdMobBridge.s_activity = new WeakReference<Cocos2dxActivity>(activity); PTAdAdMobBridge.activity = activity; PTAdAdMobBridge.initBanner(); PTAdAdMobBridge.initInterstitial(); } public static void initBanner(){ Log.v(TAG, "PTAdAdMobBridge -- initBanner"); PTAdAdMobBridge.s_activity.get().runOnUiThread( new Runnable() { public void run() { if(PTAdAdMobBridge.adView != null){ return; } FrameLayout frameLayout = (FrameLayout)PTAdAdMobBridge.activity.findViewById(android.R.id.content); RelativeLayout layout = new RelativeLayout( PTAdAdMobBridge.activity ); frameLayout.addView( layout ); RelativeLayout.LayoutParams adViewParams = new RelativeLayout.LayoutParams( AdView.LayoutParams.WRAP_CONTENT, AdView.LayoutParams.WRAP_CONTENT); adViewParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); adViewParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); PTAdAdMobBridge.adView = new AdView( PTAdAdMobBridge.activity ); PTAdAdMobBridge.adView.setAdSize(AdSize.SMART_BANNER); PTAdAdMobBridge.adView.setAdUnitId(activity.getResources().getString(R.string.admob_id_banner_admob)); layout.addView(PTAdAdMobBridge.adView, adViewParams); PTAdAdMobBridge.adView.setVisibility( View.INVISIBLE ); AdRequest adRequest = new AdRequest.Builder().build(); PTAdAdMobBridge.adView.loadAd( adRequest ); } }); } public static boolean isBannerVisible(){ if(PTAdAdMobBridge.adView == null){ return false; } else{ if(PTAdAdMobBridge.adView.getVisibility() == View.VISIBLE){ return true; } else{ return false; } } } public static void initInterstitial(){ Log.v(TAG, "PTAdAdMobBridge -- initInterstitial"); PTAdAdMobBridge.s_activity.get().runOnUiThread( new Runnable() { public void run() { if(PTAdAdMobBridge.interstitial != null){ return; } AdRequest adRequest = new AdRequest.Builder().build(); PTAdAdMobBridge.interstitial = new InterstitialAd( PTAdAdMobBridge.activity ); String admobid = activity.getResources().getString(R.string.admob_id_interstitial_admob); PTAdAdMobBridge.interstitial.setAdUnitId(admobid); if(PTPlayer.setContentView != null)PTPlayer.setContentView.setId(admobid); PTAdAdMobBridge.interstitial.setAdListener(new AdListener() { @Override public void onAdLoaded() { if(PTAdAdMobBridge.isScheduledForShow){ PTAdAdMobBridge.showFullScreen(); } } @Override public void onAdClosed() { AdRequest adRequest = new AdRequest.Builder().build(); PTAdAdMobBridge.interstitial.loadAd(adRequest); } @Override public void onAdFailedToLoad(int errorCode) { PTAdAdMobBridge.interstitialDidFail(); } }); PTAdAdMobBridge.interstitial.loadAd(adRequest); } }); } public static void showFullScreen(){ Log.v(TAG, "showFullScreen"); if(PTAdAdMobBridge.interstitial != null){ PTAdAdMobBridge.s_activity.get().runOnUiThread( new Runnable() { public void run() { if(PTAdAdMobBridge.interstitial.isLoaded()){ if(PTPlayer.is()){ if(PTPlayer.wait){ PTPlayer.wait = false; PTAdAdMobBridge.interstitial.show(); PTAdAdMobBridge.isScheduledForShow = false; }else{ PTPlayer.setContentView(); PTPlayer.wait = true; } }else{ PTAdAdMobBridge.interstitial.show(); PTAdAdMobBridge.isScheduledForShow = false; } } else{ PTAdAdMobBridge.isScheduledForShow = true; } } }); } } public static void showBannerAd(){ Log.v(TAG, "showBannerAd"); if(PTAdAdMobBridge.adView != null){ PTAdAdMobBridge.s_activity.get().runOnUiThread( new Runnable() { public void run() { AdRequest adRequest = new AdRequest.Builder().build(); PTAdAdMobBridge.adView.loadAd(adRequest); PTAdAdMobBridge.adView.setAdListener(new AdListener() { @Override public void onAdFailedToLoad(int errorCode) { PTAdAdMobBridge.bannerDidFail(); } }); PTAdAdMobBridge.adView.setVisibility( View.VISIBLE ); } }); } } public static void hideBannerAd(){ Log.v(TAG, "hideBannerAd"); if(PTAdAdMobBridge.adView != null){ PTAdAdMobBridge.s_activity.get().runOnUiThread( new Runnable() { public void run() { PTAdAdMobBridge.adView.setVisibility( View.INVISIBLE ); } }); } } } 循环中设置和测试它们

这里我的引用数组称为for。我还使用了来自List::Util@cells函数,该函数允许在一次调用中进行所有测试,并且一旦测试失败就会短路

all

答案 2 :(得分:1)

使用List::MoreUtils(或List::AllUtils)中的mapall,您可以缩短条件:

use List::MoreUtils 'all';

if ( all { $_ == 1 } map { @{ $matrix[$_][4] }, @{ $matrix[4][$_] } } 0..2, 4..6 ) { 
    say "It worked!";
}

如果您不熟悉perl中的地图和解除引用语法,则看起来有点令人困惑。 map创建了matrix[0..2,4..6][4]matrix[4][0..2,4..6]条目的列表。然后将所有这些值传递给all块,该块检查所有接收的值是否等于1.

因为matrix[n][n]会返回ARRAY引用,所以你必须取消引用它,例如。 @{ $array_ref }