Nice programing

스위치에서 케이스 문으로 배열 사용

nicepro 2020. 10. 17. 12:24
반응형

스위치에서 케이스 문으로 배열 사용


나는 이와 같은 것을 시도하고있다. 즉, switch 문에 배열을 사용한다. Java에서 가능합니까? 그렇지 않은 경우 가능한 해결책을 설명하십시오.

boolean[] values = new boolean[4];

values[0] = true;
values[1] = false;
values[2] = false;
values[3] = true;

switch (values) {
    case [true, false, true, false]:
        break;
    case [false, false, true, false]:
        break;
    default:
        break;
}

아니요 , 단순히 할 수 없습니다.

SwitchStatement:
    switch ( Expression ) SwitchBlock

Expression 형식은 char, byte, short, int, Character, Byte, Short, Integer, String 또는 enum 형식 (§8.9)이어야하며 그렇지 않으면 컴파일 타임 오류가 발생합니다.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11


@ sᴜʀᴇsʜ ᴀᴛᴛᴀ이 맞습니다. 하지만 뭔가를 추가하고 싶었습니다. Java 7부터 switch 문은 문자열을 지원하므로이를 통해 작업을 수행 할 수 있습니다. 정말 더럽고 권장하지 않지만 작동합니다.

boolean[] values = new boolean[4];

values[0] = true;
values[1] = false;
values[2] = false;
values[3] = true;

switch (Arrays.toString(values)) {
    case "[true, false, true, false]":
        break;
    case "[false, false, true, false]":
        break;
    default:
        break;
}

성능에 관심이있는 분들께 : 당신 말이 맞습니다. 이것은 매우 빠르지 않습니다. 이것은 다음과 같이 컴파일됩니다.

String temp = Arrays.toString(values)
int hash = temp.hashCode();
switch (hash)
{
    case 0x23fe8da: // Assume this is the hashCode for that
                    // original string, computed at compile-time
        if (temp.equals("[true, false, true, false]"))
        {

        }
        break;
    case 0x281ddaa:
        if (temp.equals("[false, false, true, false]"))
        {

        }
        break;

    default: break;
}

전체 어레이를 켤 수 없습니다. 그러나 약간의 가독성을 희생시키면서 비트 세트로 변환 switch 있습니다.

switch (values[0] + 2 * values[1] + 4 * values[2] + 8 * values[3])

case 문에 이진 리터럴사용 case 0b0101하십시오. 첫 번째입니다.


이 솔루션을 시도하십시오.

    boolean[] values = new boolean[4];
    values[0] = true;
    values[1] = false;
    values[2] = false;
    values[3] = true;

    if (ArrayUtils.isEquals(values, new boolean[] {true, false, true, false})) {
    ...
    }
    else if (ArrayUtils.isEquals(values, new boolean[] {false, false, true, false})) {
    ...
    }
    else {
    ...
    }

여기에서 문서를 참조 하십시오 .


예, 어레이를 스위치에 전달할 수 있습니다. 문제는 제가 Java 배열에 대해 말하는 것이 아니라 데이터 구조라는 것입니다.

배열은 일반적으로 행과 열로 된 객체의 체계적인 배열입니다.

당신이하려는 것은 다른 플래그를 인식하는 시스템을 구현하고 켜거나 끄는 플래그에 따라 다른 조치를 취하는 것입니다.

이러한 메커니즘의 일반적인 구현은 Linux 파일 권한입니다. rwx"플래그의 배열"로있는 .

전체 배열이 true이면 rwx모든 권한이 있음을 의미하는이 표시됩니다. 파일에 대해 어떤 작업도 수행 할 수없는 경우 전체 배열이 false이고 ---.

이행

정수를 배열로 생각할 수 있습니다. 정수는 "비트 배열"로 표시됩니다.

001 // 1, if on, set x 
010 // 2, if on, set w 
100 // 4, if on, set r
// putting it all together in a single "array" (integer)
111 // 2^2 + 2^1 + 2^0 = 4 + 2 + 1 = 7

그렇기 때문에 권한 rwx7

자바 스 니펫 :

class Flags {                                                                    
public static void main(String args[]) {         
        /** 
         * Note the notation "0b", for binary; I'm using it for emphasis.
         * You could just do: 
         * byte flags = 6;
         */                     
        byte flags = 0b110; // 6                     
        switch(flags) {                                                          
            case 0: /* do nothing */ break;                                      
            case 3: /* execute and write */ break;                       
            case 6: System.out.println("read and write\n"); break;         
            case 7: /* grant all permissions */ break;                           
            default:                                                             
                System.out.println("invalid flag\n");           
        }                                                                        
    }                                                                            
}

이진 형식 사용에 대한 자세한 내용은 다음 질문을 확인하십시오 . Java에서 이진 형식으로 정수 상수를 정의 할 수 있습니까?

공연

  • 메모리 절약
  • 추가 처리, 스위치 또는 기타 유형의 저글링을 수행 할 필요가 없습니다.

가능한 한 효율적이어야하는 C 프로그램은 이러한 유형의 메커니즘을 사용합니다. 단일 비트로 표시된 플래그를 사용합니다.


아니요, 할 수는 없지만 위의 코드를 다음 (더럽게 인정합니다) 코드로 바꿀 수 있습니다.

boolean[] values = new boolean[4];

values[0] = true;
values[1] = false;
values[2] = false;
values[3] = true;

switch(makeSuitableForSwitch(values)) {
   case 1010: 
     break;
   case 10: 
     break;
   default:
     break;
} 

private int makeSuitableForSwitch( boolean[] values) {
    return (values[0]?1:0)*1000+(values[1]?1:0)*100+(values[2]?1:0)*10+(values[3]?1:0);
}

조건 집합 이 참 인지 확인하려는 경우 대신 비트 필드를 사용합니다.

예를 들면

public class HelloWorld
{
  // These are the options that can be set.
  // They're final so treated as constants.
  static final int A=1<<0, B=1<<1, C=1<<2, D=1<<3 ;

  public static void main(String []args)
  {
    // Now I set my options to have A=true, B=true, C=true, D=false, effectively
    int options = A | B | C ;

    switch( options )
    {
      case (A):
        System.out.println( "just A" ) ;
        break ;
      case (A|B):
        System.out.println( "A|B" ) ;
        break ;
      case (A|B|C): // Final int is what makes this work
        System.out.println( "A|B|C" ) ;
        break ;
      default:
        System.out.println( "unhandled case" ) ;
        break ;
    }
  }
}

부울 배열의 요소 시퀀스를 기반으로 값을 계산합니다. 즉, [true, false, true, true]1011로 평가 한 다음이 정수 값을 기반으로 switch 문을 사용할 수 있습니다.


내 대답은 아니오 야. 가장 좋은 설명은 switch 문 을 사용 하는 방법을 배우는 것 입니다.


JRE 1.7부터는 해킹을 사용해야합니다. 다음을 권장합니다.

  • 취하다 values.length <= 64

  • 값을 long나타내는 비트 플래그로 변환

  • Switch16 진수 매직 넘버 에 대해

자바 코드 해킹 :

if(values.length > 64)
  throw new IllegalStateException();

long bitflags = 0x0L;

for(int i=0; i< values.length; ++i)
  if(values[i])
    bitflags |= 0x01L << i;

switch(bitflags) {
  case 0xEL: // represents [true,  true,  true, false]
    break;
  case 0xAL: // represents [true,  false, true, false]
    break;
  case 0x2L: // represents [false, false, true, false]
    break;
  default:
    break;
}

다음은 가져 오기 나 라이브러리가 필요없는 또 다른 방법입니다.

boolean[] values = new boolean[4];

values[0] = true;
values[1] = false;
values[2] = false;
values[3] = true;

int mask = buildMask(values);

if (areEquals(mask, true, false, true, false)) {
    // ...
} else if (areEquals(mask, false, false, true, false)) {
    // ...
} else {
    // ...
}

private int buildMask(boolean... values) {
    int n = 0;
    for (boolean b : values) {
        n = (n << 1) | (b ? 1 : 0);
    }
    return n;
}

private boolean areEquals(int mask, boolean... values) {
    return mask == buildMask(values);
}

이 대답은 Java 가 아니지만 Haxe는 패턴 일치 덕분에 가능하고 흥미로운 출력을 가지고 있기 때문에 원하는 것을 수행하는 스위치를 찾는 데 유용 할 수 있습니다. 배열은 고정 길이로 일치시킬 수 있습니다.

Javascript와 Flash로 컴파일되는 데모를 만들었습니다. 오른쪽 열에서 js 출력을 볼 수 있습니다.

데모 : http://try.haxe.org/#86314

class Test {
  static function main(){

    var array=[true,false,true];

    var result=switch(array){
      case [true,true,false]: "no";
      case [true,false,true]: "yes";
      default:"??";
    }

    #if js
      new js.JQuery("body").html(result);
    #elseif flash
      trace(result);
    #end

    // ouputs: "yes"
  }
}

이것은 출력 스위치이며 중첩 스위치를 사용합니다. 케이스를 가지고 놀면 js 출력이 어떻게 변경되어 효율적인 전환이 가능한지 알 수 있습니다.

(function () { "use strict";
var Test = function() { };
Test.main = function() {
    var array = [true,false,true,false];
    var result;
    switch(array.length) {
    case 4:
        switch(array[0]) {
        case true:
            switch(array[1]) {
            case false:
                switch(array[2]) {
                case true:
                    switch(array[3]) {
                    case false:
                        result = "no";
                        break;
                    default:
                        result = "??";
                    }
                    break;
                default:
                    result = "??";
                }
                break;
            default:
                result = "??";
            }
            break;
        case false:
            switch(array[1]) {
            case false:
                switch(array[2]) {
                case true:
                    switch(array[3]) {
                    case false:
                        result = "yes";
                        break;
                    default:
                        result = "??";
                    }
                    break;
                default:
                    result = "??";
                }
                break;
            default:
                result = "??";
            }
            break;
        }
        break;
    default:
        result = "??";
    }
    new js.JQuery("body").html(result);
};
var js = {};
var q = window.jQuery;
js.JQuery = q;
Test.main();
})();

밑줄을 사용할 수있는 또 다른 흥미로운 패턴입니다. _ 패턴은 모든 항목과 일치하므로 case _ :는 기본값과 동일하므로 다음을 수행 할 수 있습니다.

var myArray = [1, 6];
var match = switch(myArray) {
    case [2, _]: "0";
    case [_, 6]: "1";
    case []: "2";
    case [_, _, _]: "3";
    case _: "4";
}
trace(match); // 1

http://haxe.org/manual/pattern_matching#array-matching


또한 Groovy가 Java에서 isCase () 메서드를 구현하는 방법을 살펴보고 필요에 맞는 더 간단한 버전을 사용할 수 있습니다. 이를 인터페이스에 넣고 DSL을 만들어 애플리케이션의 두 개체를 비교할 수 있습니다.

return isCase(DefaultTypeTransformation.asCollection(caseValue), switchValue);

관련 코드는 877 행에서 982 행 까지 적용됩니다.


@Todor 네, JAVA에서 가능합니다.

boolean[] values = new boolean[4];

values[0] = true;
values[1] = false;
values[2] = false;
values[3] = true;

values = Arrays.toString(values)

switch (values) {
    case "[true, false, true, false]":
        break;
    case "[false, false, true, false]":
        break;
    case "[true, false, false, true]":
        System.out.println("YAAAAAAAAAA GOT IT");
        break;
    default:
        break;
}

참고 : 저는 자바 개발자가 아니므로 코드 구문이 잘못 될 수 있지만 논리는 완벽합니다. 내 대답을 편집 할 수 있습니다. 여기에서 배열을 문자열 형식으로 변환 한 다음 대 / 소문자를 일치 시키려고했습니다.


부울 상태를 나타내는 상수 int 값을 사용합니다.

당신이 사용하는 경우 자바 1.7 또는 이상 당신은 바이너리 리터럴 사용할 수 있습니다 더 읽기를 .

public static final int TRUE_FALSE_TRUE_FALSE = 0b1010;
public static final int FALSE_FALSE_TRUE_FALSE = 0b0010;

for Java 1.6 and below use any other int literals, e.g. hex

public static final int TRUE_FALSE_TRUE_FALSE = 0xA;
public static final int FALSE_FALSE_TRUE_FALSE = 0x2;

then create a method that converts a boolean array to an integer bitset. E.g.

public static int toIntBitSet(boolean...values){
    int bitset = 0;
    for (boolean value : values) {
       bitset = (bitset << 1) | (value ? 1 : 0);
    }
    return bitset;
}

Finally use the constants in your switch statement

boolean[] values = new boolean[]{true, false, true, false};

int bitset = toIntBitSet(values);

switch (bitset) {
  case TRUE_FALSE_TRUE_FALSE:
    System.out.println(Integer.toBinaryString(bitset));
    break;
  case FALSE_FALSE_TRUE_FALSE:
    System.out.println(Integer.toBinaryString(bitset));
    break;
  default:
    break;
}

Another approach might be to use a java BitSet and a Map that maps to the logic that should be executed depending on the bitset's value.

public static void main(String[] args) throws Exception {
  Map<BitSet, Callable<String>> bitSetMap = new HashMap<>();

  bitSetMap.put(bitSetValueOf(true, false, true, false), new TrueFalseTrueFalseCallable());
  bitSetMap.put(bitSetValueOf(false, false, true, false), new FalseFalseTrueFalseCallable());

  boolean[] values = new boolean[]{true, false, true, false};

  BitSet bitset = bitSetValueOf(values);

  Callable<String> callable = bitSetMap.get(bitset);
  if (callable == null) {
    callable = new DefaultCallable();
  }

  String result = callable.call();
  System.out.println(result);
}

public static BitSet bitSetValueOf(boolean... values) {
   BitSet bitSet = new BitSet();
      for (int i = 0; i < values.length; i++) {
         bitSet.set(i, values[i]);
      }
   return bitSet;
}

and implement your logic

class FalseFalseTrueFalseCallable implements Callable<String> {

  @Override
  public String call() throws Exception {
    return "0010";
  }

}

class TrueFalseTrueFalseCallable implements Callable<String> {

  @Override
  public String call() throws Exception {
    return "1010";
  }

}

class DefaultCallable implements Callable<String> {

  @Override
  public String call() throws Exception {
    return "default value";
  }

}

참고URL : https://stackoverflow.com/questions/20659979/use-an-array-as-a-case-statement-in-switch

반응형