Open37

teratailの回答まとめ

fj68fj68

自分がteratailで回答したもののうち、役に立ちそうなものをまとめておきます。
単純な質問と回答はteratailでも見れるので「単独で読んでも得られるものがある」「そのトピックでよく見受けられる質問に対する回答」を基準にしています。

間違いなどがあればteratail上で各回答のコメント欄にコメントいただけると助かります。

fj68fj68

Ocamlの畳み込み関数について | teratail


もうすでに解決済みかもしれませんが、何かの役に立てばと思い、回答します。

畳み込み関数について

畳み込み関数というのは、ざっくりいうと「リストの要素に順番に関数を適用してその結果を蓄積し、最後に蓄積した結果を返す」関数です。

ある整数リストの要素をすべて足した結果を返すsum関数を考えてみましょう。
リストをxs、適用する関数を+(整数の足し算)とすると、こんなイメージです。

let sum xs =
    let acc = 0           (* 初期値は 0 *)
    let x = List.nth xs 1 (* リストから1つ目の要素を取り出す *)
    let acc = acc + x     (* acc と要素 x に関数(ここでは足し算)を適用した結果を acc に覚えておく *)
    let x = List.nth xs 2 (* リストから2つ目の要素を取り出す *)
    let acc = acc + x     (* acc と要素 x に関数を適用した結果を acc に覚えておく *)
    ...                   (* これをリストの要素の数だけ繰り返す *)
    acc                   (* 最後に acc を返す *)

このような「リストからある値に『畳み込む』関数」はよく書きますので、標準のListモジュールにすでに用意されています。

val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
val fold_right: ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b

引数には「適用する関数」「初期値」「リスト」を渡します。fold_leftfold_rightで引数の順番が逆になっていますので注意です。

fold_leftはリストの左から(つまりリストの1つ目の要素、2つ目の要素……の順に)、fold_rightは右から(つまりリストの「最後から1つ目」の要素、「最後から2つ目の要素」……の順に)関数を適用していきます。

リストの最大要素を返す関数

ではfold_rightを用いてリストの最大要素を返す関数を書いてみましょう(fold_leftでも同様です)。

まず、欲しい関数の型は以下です。
わかりやすいよう、整数のリストのみ扱うことにしましょう。

val max_of_int_list: int list -> int

リストを引数に渡すと最大の要素が返ってきます。

let max_of_int_list xs =
    let init = List.hd x in    (* 初期値はリストの最初の要素とします *)
    List.fold_right (fun acc x ->
        (* acc(つまり今までで最大の要素)よりも x が大きければ acc を x とします *)
        if acc < x
        then x
        else acc
    ) xs init

これで完成です。

整数以外にも対応させたければ「ある要素が別の要素より大きいかどうか比較する関数」を引数に追加し、以下のようにすればよいでしょう。

val max_of_list: ('a -> 'a -> int) -> 'a list -> 'a
let max_of_list cmp xs =
    let init = List.hd x in    (* 初期値はリストの最初の要素とします *)
    List.fold_right (fun acc x ->
        (* cmp a b は a < b なら負数、a > b なら正数、a = b なら 0 を返す関数 *)
        if (cmp acc x) < 0
        then x
        else acc
    ) xs init

注意点

Listモジュールのfold_rightは末尾再帰ではありませんので、大きなリストに対して使うとスタックオーバーフローする可能性があります。そのときは何回かに分けるか、末尾再帰に書き直しましょう。
fold_leftは末尾再帰です。

また、上記のmax_of_int_listmax_of_listは初期値として最初の要素を渡しているため、最初の1回の比較は無駄ですし、空リストに対しては例外が発生します。わかりやすさ優先としたので、気になるようなら書き直してください。

fj68fj68

Ocamlの型変換について | teratail


すでに解決済みかもしれませんが、同じような方がいるかもしれないので回答します。

functionについて

OCamlのfunctionキーワードはlet f x = match x with ...のショートハンドです。
そのため、let rec string_of_exp v = function ...の引数vは不要です。

ご参考までに、以下のfgは同じです。

let f x =
    match x with
    | None -> "None"
    | Some v -> v
let g = function
    | None -> "None"
    | Some v -> v

string_of_expを書く

以上の話を踏まえ、関数string_of_expの型を考えます。
欲しい関数はデータ型expstringに変換する関数ですから、以下のような型の関数になります。

val string_of_exp : exp -> string

では、各パターンマッチでstringを返すように関数を書いていきましょう。

let rec string_of_exp = function
    | Num n -> (* n: int を string に変換する式 *)
    | Var v -> (* v: string を string に変換する式 *)
    | Add (x, y) -> (* x: exp, y: exp を string に変換する式 *)
    | Mul (x, y) -> (* x: exp, y: exp を string に変換する式 *)

引数がNumのときはstring_of_intでstringに変換します。

let rec string_of_exp = function
    | Num n -> string_of_int n

引数がVarのときは値がstringということでおそらく変数名でしょうから、そのまま返します。

let rec string_of_exp = function
    | Var v -> v

引数がAddのときは(値 + 値)と表示するか足し算した結果を表示するかによりますが、今回は「exp 型の数式の文字列表現」ということなので、前者とします。

let rec string_of_exp = function
    | Add (x, y) -> Printf.sprintf "(%s + %s)" (string_of_exp x) (string_of_exp y)

引数がMulのときもAddと同様に(値 * 値)と表示することにします。

let rec string_of_exp = function
    | Mul (x, y) -> Printf.sprintf "(%s * %s)" (string_of_exp x) (string_of_exp y)

以上をまとめて、string_of_expは以下のようになります。

let rec string_of_exp = function
    | Num n -> string_of_int n
    | Var v -> v
    | Add (x, y) -> Printf.sprintf "(%s + %s)" (string_of_exp x) (string_of_exp y)
    | Mul (x, y) -> Printf.sprintf "(%s * %s)" (string_of_exp x) (string_of_exp y)

参考情報

以下にpuroさんが書かれたコードにでてくるいくつかの式の型を書いておきます。
int_of_expmake_sumがどういった関数なのか不明だったので、一部は関数名から想像した型を前提に書いています。

string_of_int n     (* string *)
int_of_exp x        (* int_of_exp: exp -> int なら int *)
(x+y)               (* x: exp, y: exp なので対応する + が定義されておらず、型エラー *)
make_sum (...)      (* make_sum: int list -> int なら int *)

注意点

わかりやすさを優先し、以上のstring_of_expは末尾再帰になっていません。
大きな式を文字列に変換しようとするとスタックオーバーフローする可能性があるので、そのときは何回かに分けて呼び出すか、関数を末尾再帰に書き直してください。

以上、お役に立てれば幸いです。

fj68fj68

カンマ区切り複数の値を表示 | teratail


1. array_map()implode()を使う方法

array_map()$items1<a 〜>〜</a>という文字列の配列に変換した後、implode()で「、」を挿入し、出力する方法です。
個人的にはこちらのほうが素直な解法かと思います。

echo implode("、", array_map(
    fn($value) => '<a href='.$url.'/meta?key=team&value='.$value.'>'.$value.'</a>',
    $items1
))

2. foreachを使う方法

foreachで繰り返すときに要素のインデックスも取得するようにし、最後の要素でなければ「、」を出力する方法もあります。

$last_index = count($items1) - 1;

foreach($items1 as $index => $value) {
    echo '<a href='.$url.'/meta?key=team&value='.$value.'>'.$value.'</a>';
    if ($index != $last_index) { // 最後の要素でない場合
        echo '、'
    }
}

参考

fj68fj68

読み上げ音声をローカルファイルに | teratail


Google Cloud Text-to-Speechを使いましょう。

base64で音声データが帰ってきますのでmp3ファイルにデコードすれば出来上がりです。

const textToSpeech = require('@google-cloud/text-to-speech');
const fs = require('fs');
const util = require('util');

const client = new textToSpeech.TextToSpeechClient();
const text = 'こんにちは';
const outputFile = 'output.mp3';

const request = {
  input: {text: text},
  voice: {languageCode: 'ja-JP', ssmlGender: 'FEMALE'},
  audioConfig: {audioEncoding: 'MP3'},
};
const [response] = await client.synthesizeSpeech(request);
const writeFile = util.promisify(fs.writeFile);
await writeFile(outputFile, response.audioContent, 'binary');
console.log(`Audio content written to file: ${outputFile}`);
fj68fj68

PyrhonのTkinterをつかってグラフを画面の真ん中に表示させたい | teratail


gridを中央に表示するには、grid()で配置する要素の親要素にgrid_anchor(tkinter.CENTER)を使います。

import tkinter as tk

root = tk.Tk()

# gridを中央に寄せる
root.grid_anchor(tk.CENTER)

frame = tk.Frame(root)
frame.grid() # 親要素rootのgrid(row=0, column=0)に配置

イメージとしては、親要素がgridという要素を持っていて、その中にframeborderを配置するイメージです。
そして、そのgrid自体の配置場所を中央にするメソッドがgrid_anchor()です。

grid()anchor引数は「gridセル内のどこに要素を配置するか」を決めるものなので、子要素が1つしか無くgrid自体を中央に持ってきたい今回の場合は指定しても見た目の変化がありません。

ご質問のコードでは一つの要素が一つの子要素を持つので、rootgrid_anchor(tkinter.CENTER)を設定すればあとは設定しなくてもよいでしょう。

なお、root.geometry('700 x 500')はエラーが出るので、修正しました。

import tkinter as tk

root = tk.Tk()
root.title("Application")
root.resizable(width=False,height=False)
root.geometry('700x500')

# gridを中央に配置
root.grid_anchor(tk.CENTER)

frame = tk.Frame(root, width=700, height=300, bg="red")
frame.grid()

border = tk.LabelFrame(frame, text="Form", fg='white', bg='#444', relief=tk.FLAT)
border.grid()
innerBox = tk.Frame(border, width=300, height=100)
innerBox.grid()

root.mainloop()

ではなぜ質問にあるような状態になったのでしょうか。
それぞれどうなっているのかを確認してみましょう。

まずご質問にある1つ目のコードです。

import tkinter as tk

# 1. メインウィンドウの作成
root = tk.Tk()
root.title("Application")
root.resizable(width=False,height=False)
root.geometry('700x500')

frame = tk.Frame(root, width=700, height=300, bg="red")
frame.grid()    # これはrootのgrid(row=0, column=0)に配置される

border = tk.LabelFrame(frame, text="Form", fg='white', bg='#444', relief=tk.FLAT)
border.grid()   # これはframeのgrid(row=0, column=0)に配置される
innerBox = tk.Frame(border, width=300, height=100)
innerBox.grid() # これはborderのgrid(row=0, column=0)に配置される

root.mainloop()

このコードではrootframegridで配置し、frame内にbordergridで配置しています。
このときrootgridは上部に表示され、gridのサイズは子要素に合わせられます。
これはframegridも同様です。

すると、borderframegrid内の上部、framegridframe内の上部、frameroot内のgridの上部、そしてrootgridrootの上部、といった配置になり、それぞれのgridのサイズは子要素に合わせられますので、結果的にborderが左上に配置されたように見えます。

一方、ご質問の2つ目のコードではframeborderrootgridで配置されています。
border.grid()と「どのセルに配置するか」を指定していませんので、frameの下のセルに追加されることに注意です。

import tkinter as tk

root = tk.Tk()
root.title("Application")
root.resizable(width=False,height=False)
root.geometry('700x500')

frame = tk.Frame(root, width=700, height=300, bg="#000080")
frame.grid()    # これはrootのgrid(row=0, column=0)に配置される

border = tk.LabelFrame(root, text="Form", fg='white', bg='#444', relief=tk.FLAT)
border.grid()   # これはrootのgrid(row=1, column=0)に配置される
innerBox = tk.Frame(border, width=300, height=100)
innerBox.grid() # これはborderのgrid(row=0, column=0)に配置される

root.mainloop()

rootgridrootの上部に表示され、その内部にframeborderが縦に配置されます。
このときgridのセルの大きさは一番大きいセルに合わせられますのでframeの大きさになります。
結果、borderの左右と下に隙間ができ、中央に表示されたように見えるのです。

回答のコードではrootgridを中央に配置しています。
その結果、borderframegridの上部、framegridframeの上部、framerootgridの上部、rootgridrootの中央部に表示され、それぞれgridのサイズは子要素のサイズに合わせられますのでborderが中央に表示されたように見えるのです。

以上、一部わかりにくかったかもしれませんが、お役に立てれば幸いです。

fj68fj68

python tkinterについて | teratail


さて、ご質問の「Frame.py を起動した際に、radio.pyを表示させたい」というのは「radio.pyにTk関係のコードを集約し、frame.pyから呼び出したい」ということでしょうか。
それとも「2つのTkアプリケーションを同時に起動したい」ということでしょうか。
ちょっとわからなかったので、それぞれ回答します。

frame.pyからradio.pyを呼び出す

これは単純で、radio.pyのコードを関数にしてframe.pyでインポートし、適宜関数を呼んであげればOKです。

その際、radio.pyの関数にrootを作って渡したほうがroot.mainloop()まで関数にするよりは再利用性が高まると思います。

コードはこんな感じです。

frame.py

from tkinter import *
from tkinter import ttk

import radio      # radio.pyをインポート

root = Tk()
root.title('Frame Test')

radio.frame(root) # radio.pyの関数にrootを渡してあげる

root.mainloop()

radio.py

from tkinter import *
from tkinter import ttk

def button1_clicked():
    print('v1 = %s' % v1.get())
    quit()

def rb_clicked():
    print('v1 = %s' % v1.get())

def create(root):
    # Frame
    frame1 = ttk.Frame(root,padding=10)
    frame1.grid()
    # ...いろいろつくる...

2つのTkアプリケーションを同時に起動する

Tkは基本的に1つプロセス内では1つのTkアプリケーションしか起動できないので、これはちょっと面倒になります。
いくつか方法はありますが、一番単純なのはサブプロセスを2つ起動してその中でTkアプリケーションをそれぞれ起動する方法でしょう。

サブプロセスを2つ同時に起動するにはmultiprocessingモジュールを使います。

multiprocessing --- プロセスベースの並列処理 ― Python 3.10.0b2 ドキュメント

frame.py

from tkinter import *
from tkinter import ttk
import multiprocessing as mp
import radio    # radio.pyをインポート

def frame():
    root = Tk()
    root.title('Frame Test')
    
    frame1 = ttk.Frame(
        root,
        height=200,
        width=300,
        relief='sunken',
        borderwidth=5)
    frame1.grid()
    
    root.mainloop()

frame_p = mp.Process(target=frame)        # frame用のプロセスを作る
radio_p = mp.Process(target=radio.main)   # radio用のプロセスを作る
frame_p.start()   # frame用のプロセスを起動する
radio_p.start()   # radio用のプロセスを起動する

radio.py

from tkinter import *
from tkinter import ttk

def button1_clicked():
    print('v1 = %s' % v1.get())
    quit()

def rb_clicked():
    print('v1 = %s' % v1.get())

def main():
    root = Tk()
    root.title('Radiobutton 1')

    # Frame
    frame1 = ttk.Frame(root,padding=10)
    frame1.grid()
    
    # ...いろいろつくる...
    
    root.mainloop()

以上、お役に立てれば幸いです。

fj68fj68

Discord、合言葉BOTの制作 | teratail


正直、discord.pyには詳しくありませんが、調べてみるとDMでも基本は普通のコマンドbotと変わらないようです。
ただしDMの場合、ctx.message.guildNoneになってしまうそうなので、事前にguildroleを取得しておきましょう。

また、DMChannelからのメッセージの場合、context.message.authorMemberではなくUserとなります。
Member.add_roles()を使うためにはguild.get_member(context.message.author.id)で改めて対応するMemberオブジェクトを取得する必要があります。
そして、guild.get_member()を使用するにはIntentsというオブジェクトを使ってオプションを設定してあげる必要があります。

以下のコードではトークンや合言葉など見られてはまずいものを環境変数から読み込むようにしていますので、HerokuのConfig Varsに適宜設定するか書き換えてください。

【追記】
add_role()の2つ目以降の引数に?rの引数が渡されるので、いくつ渡されてもいいように可変引数とし、引数がなかったり引数に渡されたフレーズが間違っていれば「合言葉が間違っています」と表示するようにしました。

import discord
from discord.ext.commands import Bot
import os
import traceback


TOKEN = os.getenv('DISCORD_BOT_TOKEN')
GUILD_ID = int(os.getenv('DISCORD_BOT_GUILD_ID'))
ROLE_ID = int(os.getenv('DISCORD_BOT_ROLE_ID'))
WORD = os.getenv('DISCORD_BOT_WORD')


intents = discord.Intents.default()
intents.members = True
bot = Bot(command_prefix='?', intents=intents)


guild = None
role = None


@bot.event
async def on_ready():
    global guild
    global role
    guild = bot.get_guild(GUILD_ID)
    role = guild.get_role(ROLE_ID)


@bot.event
async def on_command_error(ctx, error):
    orig_error = getattr(error, "original", error)
    error_msg = ''.join(traceback.TracebackException.from_exception(orig_error).format())
    await ctx.send(error_msg)


def is_DM(message):
    return isinstance(message.channel, discord.DMChannel)


@bot.command(name='r')
async def add_role(ctx, *args):
    """DM経由かつ合言葉が合っていれば役職を付与"""
    # 「?r あああ いいい」 → add_role(ctx, ['あああ', 'いいい']) → 'あああ いいい'
    # 「?r」 → add_role(ctx, []) → ''
    word = ' '.join(args)
    if role is not None and is_DM(ctx.message) and word == WORD:
        user = guild.get_member(ctx.message.author.id)
        await ctx.send("役職を付与しました。")
        await user.add_roles(role)
    else:
        await ctx.send('合言葉が間違っています。')

bot.run(TOKEN)

Botの権限も重要です。
Discord Developer PotalでBotをサーバに登録するためのURLを生成するときにBotの権限を指定します。
Manage RolesやSend Messagesが必要になります(とりあえず全部与えて試していたので、もしかしたら他にも必要な権限があるかもしれません)。
同時に、2つあるインテントの設定もオンにしてください。
詳しくは以下の質問の回答が画像付きなのでおすすめです。

Discord - How to give my bot permissions. [Javascript] - Stack Overflow

その上で、サーバーの設定画面でBot用の権限(自動で作成されます)が他の権限よりも上に来るように設定しましょう。
これをしないと一部のユーザに対して操作できなくなったりするそうです。

参考:

以下、少し見にくいかもしれませんが、動作した環境の各種設定です。
権限はサーバの設定から変更することはできず、Botを導入するためのURLを生成するときにしか指定できませんので、変更したい場合は一度Botをサーバから削除して導入し直す必要があるようです。
Botの削除は「サーバの設定→Integrations→Bot名→Delete Integration」で可能です。





以上、お役に立てれば幸いです

fj68fj68

C言語 行列 代入/表示 | teratail


yama[i][j]charですので、printf()のフォーマット指定子は%cを使います。

参考:フォーマット指定子一覧

for(i = 0;i < a;i++){
  for(j = 0;j < b;j++){
    printf("%c", yama[i][j]);
  }
  printf("\n");
}

ただ、上記の方法はprintf()を無駄に呼びすぎです。
yama[i]の末尾にNull文字\0をつけて文字列にし、%sで表示するとよいでしょう。

for(i = 0;i < a;i++){
  for(j = 0;j < b;j++){
    yama[i][j] = 'X';
  }
  yama[i][j+1] = '\0';  // 末尾にNull文字を追加して文字列にする
}
for(i = 0;i < a;i++){
  printf("%s\n", yama[i]);
}

一応、j+1MAX2を超えないよう注意してください。
ご参考まで。

fj68fj68

リアクションを付けたい | teratail


どのライブラリを使われているかわかりませんが、コードから察するにdiscord.jsでしょうか。
であれば、message.react('絵文字')でできます。

Message ― discord.jsのドキュメントより以下引用します。

message.react('🤔')
  .then(console.log)
  .catch(console.error);

// カスタム絵文字を使う場合は以下

message.react(message.guild.emojis.cache.get('123456789012345678'))
  .then(console.log)
  .catch(console.error);

追記

メッセージが作成されたときにそのメッセージがbotのものならリアクションをつければOKではないでしょうか。

client.on("messageCreate", async message => {
  if (message.author.bot) {
    message.react('🤔');
    return;
  }
  /* ...その他いろいろやる */
}

自分のメッセージだけにつけたいなら以下です。

if (message.author.id === client.user.id) { /* ... */ }
fj68fj68

canvasで表示した画像を中央表示の状態で、inputのrangeを使って拡大・縮小したい。 | teratail


まず、Canvasで画像を拡大縮小する方法についてですが、drawImage()だけでできます。

/* drawImage(Image, コピー元 X, コピー元 Y, コピー元 Width, コピー元 Height,
 *                  コピー先 X, コピー先 Y, コピー先 Width, コピー先 Height);
 */
context.drawImage(img, 0, 0, img.width, img.height,
                       0, 0, img.width * scale, img.height * scale);

その上で、画像の描画位置を中央にすればよいので、以下のようになります。
ご質問のコードにある「canvasサイズ-画像サイズ/2で中央に表示」と同じです。

// スライダーが動いたら拡大・縮小して再描画する
slider.addEventListener('input', e => {
    // 一旦クリア 
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // 倍率変更
    const scale = Number(e.target.value);
    // 再描画
    ctx.drawImage(img, 0, 0, img.width, img.height,
                  (canvas.width - img.width * scale) / 2,
                  (canvas.height - img.height * scale) / 2,
                  img.width * scale, img.height * scale);
});

参考:クライアント側でcanvasを使って画像をリサイズする - Qiita

fj68fj68

jsonの特定の値を配列で格納する処理をスマートに書きたい | teratail


mapとdestructuringを使うのはいかがでしょう。

const users = json.values.map(({ userId }) => userId);
const counts = json.values.map(({ count }) => count);

細かいことですが、usersよりもuserIdsの方が適切かな、と思います。
ご参考まで。

追記

なぜ上記のコードになるのか、一応書いておきます。

const users = [];

json.values.forEach(value => {
  users.push(value.userId);
})

まず、forEachmapに書き換えます。
mapはある配列の要素を順番に取り出し、関数を適用した結果の配列を作ります。
やっていることは上のコードと同じでして、json.valuesから要素を1つ({ userId: 120, count: 0 })順に取り出して「なにかして」その結果を配列にします。

const users = json.values.map(なにかする関数);

この「なにかする関数」のところが「{ userId: 120, count: 0 }からuserIdの値をとってくる」という関数であればいいわけです。

つまり、こうなります。

const users = json.values.map(value => value.userId);

ここで、JavaScriptには分割代入という機能があります。

const value = { userId: 120, count: 0 };
const { userId, count } = value;
console.log(userId); // 120
console.log(count);  // 0

これは関数の引数でも使えるので、「{ userId: 120, count: 0 }からuserIdの値をとってくる」関数はこうなります。

const getUserIdOf = ({ userId }) => userId;
const value = { userId: 120, count: 0 };
console.log(userIdOf(value)); // 120

あとはこれらを組み合わせれば、冒頭の回答コードになります。

filterforEachも同じようなものです。「なにかをする」関数の部分がちょっと変わるだけです。
でもとても便利なので、使えるようになると読みやすいコードが書けるようになると思います。
幾分慣れの部分がありますので、頑張ってください!

fj68fj68

[TypeScript]複数の型を組み合わせて定義した型で、Property 'xxxx' does not exist on typeが発生する | teratail


判別可能なUnion型とユーザ定義のType Guardを組み合わせましょう。
型チェックやインテリセンスも効くようになり便利です。

判別可能なUnion型 - TypeScript Deep Dive 日本語版

interface Sample1 {
    kind: 'Sample1';  // これで判別する
    id:   string;
    name: string;
}

interface Sample2 {
    kind:  'Sample2';  // これで判別する
    id:     string;
    gender: string;
}

type Sample1and2 = Sample1 | Sample2

// ユーザ定義のType Guard
function isSample1(x: Sample1and2): x is Sample1 {
    return x.kind === 'Sample1'
}

// ユーザ定義のType Guard
function isSample2(x: Sample1and2): x is Sample2 {
    return x.kind === 'Sample2'
}

const sampleFunc = ({
  sample
}: {
  sample: Sample1and2
}) => {
    if (isSample1(sample)) {
        console.log(sample.id, sample.name);
    } else {
        console.log(sample.id, sample.gender);
    }

    /* switch-caseでもOK */
    switch (sample.kind) {
        case 'Sample1':
            console.log(sample.id, sample.name);
            break;
        case 'Sample2':
            console.log(sample.id, sample.gender);
            break;
        default:
            // これを書いておくとSample1and2に型を足したときにここでエラーが出るようになり、
            // caseを増やすのを忘れにくくなります。
            const _exhaustiveCheck: never = sample;
    }
}

別解としてasでキャストすることもできますが、おすすめしません。

以上、ご参考になれば幸いです。

fj68fj68

GASのUrlFetchAppのGETメソッドでのパラメータの渡し方 | teratail


Class UrlFetchApp | Apps Script | Google Developpers

管見の限りでは見つかりませんでした。
代わりにこんな感じでどうでしょうか。

function urlOf(url, params) {
    return `${url}?${Object.entries(params).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&')}`;
}

UrlFetchApp.fetch(urlOf("https://www.google.co.jp/search", { q: 'fetch やり方' }))
fj68fj68

reactでuseEffectでREST APIを叩いて得たデータをpropsとして渡したい | teratail


子コンポーネントのuseEffectの実行は子コンポーネントが初期化された時点で起こります。
するとまだ親コンポーネント内でのfetcher()が終わっていないため、初期値の"takeshi"props.nameに渡されて子コンポーネントのnameにセットされ、その後props.nameが変更されてもuseEffect(..., [])なので実行されず子コンポーネントのnameが初期値のままになっているのだと思います。

解決策としてはuseEffect()の第2引数にprops.nameを追記するか……

//Child.tsx

const Parent: React.FC = (props) => {
  const [name, setName] = useState('takeshi')

  useEffect(() => {
    setName(props.name)
  }, [props.name])    // 依存先にprops.nameを追加

  return (
    <p>{name}</p> //ここではtakeshi
  )
}

子コンポーネントでnameというStateを用意せずにprops.nameを使うかすればよいかと。

//Child.tsx

const Parent: React.FC = (props) => (
  <p>{props.name}</p> // 単純にprops.nameを使う
)

個人的には子コンポーネント内でStateを持つと同じ値を2つのコンポーネントで同時に状態管理するといういびつな形になってしまうので、状態管理は親コンポーネントに任せて子コンポーネントは値を使うだけの2つ目の方法がおすすめです。

fj68fj68

Discord.jsでメッセージにキーワードが含まれている場合、既定の候補の中からランダムでメッセージを送信する | teratail


ご質問に書かれている情報が乏しく、正しく意図を読み取れているかわかりませんが、こういう感じでどうでしょうか。

キーワードをいくつか指定できるように、Array.prototype.some()String.prototype.includes()を組み合わせます。
そして、引数のうち1つをランダムに返すoneOf()を定義しました。

トークンは環境変数APP_TOKENから読み込むようにしてあります。

const { Client, Intents } = require('discord.js');

const client = new Client({ intents: Object.keys(Intents.FLAGS) });

/* 引数のうち1つをランダムに返す */
function oneOf(fst, ...rest) {
  const xs = [fst, ...rest];
  const i = Math.floor(Math.random() * xs.length);
  return xs[i];
}

client.on('messageCreate', async message => {
  if (message?.author?.bot) {
    // 無限ループを避けるため、Botのメッセージは無視する
    return;
  }
  const msg = message.content ?? '';
  if (['こんばんは', 'こんばんわ'].some(s => msg.includes(s))) {
    await message.channel.send(oneOf('こんばんは〜', 'ばんわ', 'こん!'));
  }
});

client.login(process.env.APP_TOKEN)
fj68fj68

GAS スプレッドシートの文字列を時間として取得してカレンダーにエクスポートしたい | teratail

他の回答者の回答も参考になる。


Date.prototype.setHours()Date.prototype.setMinutes()は時・分・秒などそれぞれの整数値を引数に指定します。
13:00のような文字列だとうまくいかないので、事前にパースするとよいでしょう。
設定するだけならDate.prototype.setHours()で時・分・秒・ミリ秒まで一括で指定できます。

Date.prototype.setHours() - JavaScript | MDN

/* '13:00'→[13, 0]にする関数 */
function parseHours(hours) {
    return hours.split(':').map(v => Number(v));
}

/* ...省略... */
var startDate = new Date(day);
startDate.setHours(...parseHours(startTime));
fj68fj68

Discord.jsでコマンドごとにファイルを分けて実行する | teratail


単純にファイルを分けたいだけなら、client.on(〜)の部分を関数にして呼び出せばよいと思います。

// main.js

const Discord = require('discord.js')
const on_message = require('./on_message.js')

const client = new Discord.Client({ intents: [Discord.Intents.FLAGS.GUILDS, Discord.Intents.FLAGS.GUILD_MESSAGES] });
const prefix = "!";

on_message(client)

client.login('Botのトークン')
// on_message.js

function on_message(client) {
    client.on('message', message => {
        if (message.content === `${prefix}ping`) {
            message.channel.send('Pong.');
        } else if (message.content === `${prefix}beep`) {
            message.channel.send('Boop.');
        }
    });
}

module.exports = on_message

ただ、大量にある場合は以下のようにイベントの配列を作った方が管理しやすいかなと思います。

// main.js

const Discord = require('discord.js')
const events = require('./events.js')

const client = new Discord.Client({ intents: [Discord.Intents.FLAGS.GUILDS, Discord.Intents.FLAGS.GUILD_MESSAGES] });
const prefix = "!";

// eventsを全てclientに登録
events.forEach(({name, handler}) => client.on(name, handler));

client.login('Botのトークン')
// events.js

// イベント
const events = [
    require('./on_message.js'),
]

module.exports = events
// on_message.js

const name = 'message'

const handler = message => {
    if (message.content === `${prefix}ping`) {
        message.channel.send('Pong.');
    } else if (message.content === `${prefix}beep`) {
        message.channel.send('Boop.');
    }
}

module.exports = {name, handler}
fj68fj68

python:スクレイピングで特定のボタンがあるときのみ、該当箇所をクリックする方法 | teratail


複数の要素を取得するには、find_elements()を使います。
特定のボタンがあるかどうかは返値が空配列かどうかを見ればわかりますし、forを使えば空配列の場合は実行されません。

from selenium import webdriver
from selenium.webdriver.common.by import By

options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)  

driver.get('取得したいサイトのURL')

links = driver.find_elements(By.CSS_SELECTOR, "a[target='QD']")
for link in links:
    link.click()
    # その他色々する

find_element()などで1つづつ取得する時はNoSuchElementExceptionが発生したかどうかを確認すれば要素があるかわかります。

from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException

def find(driver, selector):
    try:
        return driver.find_element(By.CSS_SELECTOR, selector)
    except NoSuchElementException:
        return None

link = find(driver, 'a[target="QD"]')
if link is not None:
    link.click()
    # その他色々する

4. Locating Elements - Selenium Python Binding 2 documentation

fj68fj68

Discord.jsでevalコマンドを実装したい(危険を承知で) | teratail


まず、再三考えたことでしょうが、evalではなくFunctionJS-Interpreterといった他の方法で実現できないか今一度よく検討してみてください。

eval() - JavaScript | MDN - より安全なFunctionを使う方法などが紹介されています。
絶対にevalを使うな! - Discord.js Japan User Group - evalの代替ライブラリなどが載っています。

その上で、どうしてもevalしたいという場合は、以下が参考になるかもしれません。

Making an Eval command

JavaScriptを実行するサーバを用意して実行したい文字列を送信し、実行結果を返すことでevalを避ける方法もあります。その場合はまた別のセキュリティリスクがありますが。

どのような目的でevalされたいのかを書いていただければ具体的な回答を得られるかもしれません。
私はdiscord.jsでevalしたことがなく、自分がevalを使ってコードを書いてもどなたかに使ってもらえるほど安全なものになるとは思えないので、このような回答になってしまいます。すみません。
ご参考まで。

fj68fj68

ループ処理を理解したい | teratail


for line in fとあるので、forの中身はfの行数分、実行されます。
そのとき、dt = ast.literal_eval(line)と結果をdtに代入していますが、この行が実行される度にdtに代入しているため、最後の結果しかdtに残りません。

forのイメージはこんな感じです。

xs = ['a', 'b', 'c']
for x in xs:
    di = x
print(di)

# 以下と同じ

x = xs[0]
di = x
x = xs[1]
di = x
x = xs[2]
di = x
print(di)

そのため、意図した結果を取得するにはforの中にprint()を入れて毎回print()するか、結果を保持する変数を作ってfor内が実行される度にそこに追加していくかする必要があります。

# ① 毎回 print()
for line in f:
    di = ast.literal_eval(line)
    print(di['eval_loss'])  # 毎回出力するようにする
# ② 一旦リストに保存
results = []
for line in f:
    di = ast.literal_eval(line)
    results.append(di['eval_loss'])
print(results) # [0.6871868968009949, 0.6824596524238586, ...]

個人的には内包表記をおすすめします(やっていることは上の②のコードと同じで、書き方が違うだけです)。

results = [ast.literal_eval(line) for line in f]
print(di['eval_loss'] for di in results)

# または

print(ast.literal_eval(line)['eval_loss'] for line in f)
fj68fj68

javascriptでsrc内に変数を用いたい | teratail


【追記】
<noscript>について、「<noscript>はJavaScriptが無効な環境で表示されるので、imgを追加するのは無意味ではないか」とご指摘をいただきました。
そのとおりです。コードと説明を修正しました。


<script src="'https://example.com/1/?code='+ hoge" id="aaa"></script>はHTMLであり、"'https://example.com/1/?code='+ hoge"もまたHTMLの一部分です。JavaScriptとして実行されるわけではありません。

ご質問にある参考文献はVueというライブラリを用いてHTMLを動的に生成しているのでこのようなことができますが、ご質問から察するにgara-pagosuさんはそういったライブラリを使っていないのではないかと思います。

その場合は、以下のようにJavaScriptで動的に<script>要素を作ってドキュメントに追加すれば読み込むことができます。

スクリプトを動的に読み込む方法 | JavaScript プログラミング解説

imgタグについては<noscript></noscript>内の要素をJavaScriptでは操作できないので(JavaScriptが無効の環境向けですからね……)、サーバーサイドでHTMLを生成するなどの方法をとりましょう。

<script>
  var hoge = "abc";

  // script要素を作る関数
  function createScript(src, klass) {
    var script = document.createElement("script");  // script要素を作る
    srcipt.classList.add(klass);                    // idではなくclassを追加(下記の説明を参照)
    script.src = src;                               // srcを設定
    return script;
  }

  // ドキュメントが完全に読み込まれてから
  document.addEventListener('load', () => {
    // script要素を作ってbodyに追加
    var s1 = createScript('https://example.com/1/?code=' + hoge, "aaa");
    document.body.appendChild(s1);
    var s2 = createScript('https://example.com/2/?code=' + hoge, "aaa");
    document.body.appendChild(s2);
  });
</script>

なお、var hoge = abc;abcは変数名ではなく文字列でしょうから、"abc"に修正しました。
また、HTMLではid属性はドキュメント内で一意でなければなりません。言い換えると、ドキュメント内で同じidは2つの要素につけることができないのです。そのため、id="aaa"class="aaa"となるよう変更しました。

クライアントサイドでスクリプトを動的に読み込む方法を書いておいて何なんですが、他の方も回答されているように今回のケースではサーバーサイドでHTMLを動的に生成する方法がよいのではないかと思います。

ご参考まで。

fj68fj68

git push origin masterの不明な挙動 | teratail


1. パスワードを入力しているのに表示されない

これは正常な動作です。
「ショルダーハッキング」という「パスワードを入力しているところを肩越しに見て覚えることでパスワードを盗み出す」方法に対する対策として、入力した文字が表示されないようになっているのです(ATMに後ろを見る鏡がついているのもこのハッキング方法に対する対策です)。
そのため、パスワードを入力してEnterキーを押せば、表示はされませんがちゃんと入力できています。
sudoなど、他のコマンドでも同じようになっていることが多いです。

2. git pushするには

GitHubにはパスワードによるログインはできません。
SSH接続することをおすすめします。
以下にやり方が書いてあります。

GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~ - Qiita

【追記】
環境情報を見落としておりました。
Windows 10の場合はこちらが参考になると思います。
失礼しました。

【初心者向け】GitHubにSSH接続する設定方法 for Windows 10 | Techs Report

基本的な手順は

  1. 手元のPCでSSH Key(パスワードの代わり)を生成する
  2. 公開鍵と秘密鍵が出来るので、公開鍵をGitHubに登録する

だけです。
ただし場合によっては追加でいくつか設定する必要があります(上記の記事に書かれています)。
上記の記事をよく読んで、試してみて出来なければまた質問してください。

SSH接続をすると、Gitを使ってGitHubアカウントにログインしてきたPCがちゃんとそのGitHubアカウントの所有者のものかをGitHubが確認することができます。
と同時に、Gitは事前に設定してあるSSHの情報を使えば、git pushの度に一々パスワードやアカウント名を聞かなくて済みます。
毎回入力するパスワードの代わりに事前にSSHキーを設定しておいて、それを使ってGitHubにログインするわけです。

この設定はPC毎に行う必要はありますが、1度設定してしまえばアカウントやパスワードの入力を省略できてセキュアなためおすすめ、というわけです。

3. GitとGitHub

余談ですが、gitコマンドとGitHubの関係をおさらいしておきます。

Gitはバージョン管理システムの一種で、gitコマンドを用いてファイルやフォルダの変更内容を記録しておくことができます。
この記録は「リポジトリ」単位で行われます。
また、Gitは「リモートリポジトリ」と呼ばれるネット上にあるリポジトリと「ローカルリポジトリ」と呼ばれる手元のPCにあるリポジトリを同期する機能があります。

GitHubはGitのリモートリポジトリをホストできるサイトで、リポジトリの変更内容を見たり、編集したりできます。
Gitリポジトリ専用のGoogle Driveのようなものですね。
同じようなサービスとしてGitHub以外にもGitLabやBitBucketなどがあります。
GitHubを含め、これらホスティングサービスはGitとは独立したプロジェクトでして、Gitはそういったサービスなしでも使うことができます。

そして、つい先日までは、GitのリモートリポジトリにGitHub上のリポジトリを指定している場合、GitHubのユーザー名とパスワードを入力してログインすることで同期できるようになっていました。
しかし、セキュリティの観点からパスワードを使ったログインが廃止され、従来からあったSSHキーを登録してSSH接続する方法か、GitHub上でアクセストークンを発行しそれを使ってログインする方法でしかGitHubにログイン出来ないようになりました。
そのため、Gitがユーザーにパスワードを入力してもらいそれを使ってログインしようとすると、GitHubから「パスワードによるログインが廃止された」旨のメッセージが送り返され、ユーザーに該当のエラーが表示されるのです。

fj68fj68

gitlab上の添付ファイル名の検索方法


軽く調べた限りではありますが、以下の情報がありました。

  1. GitLab自体のIssueに同様の要望がありました。
    ただ、1年前から存在しOpenのままなので、残念ながらGitLabの機能としては実装されていないと見るべきかもしれません。
    Search: attachments. (#214604) · Issues - GitLab.org

  2. GitLab APIのNotes APIでProjectごとのIssue Note(Issueのコメントに相当)を取得するとattachmentsプロパティがあるようなので、使えるかもしれません。自分でプログラムを書かねばなりませんが……
    List project issue notes - Notes API | GitLab

以上、ご参考まで。

fj68fj68

指定した時間で繰り返しの処理を止めたい | teratail


【追記】
clock_gettime()を使ったコードに変更しました。

clock_gettime()timespec型の値を返し、timespec型は秒とナノ秒の情報が入った構造体です。
clock_gettime(CLOCK_MONOTONIC, &timespec型の変数)とすると単調増加の値が得られます。
計測を始めた時点の値と現在の値の差が10秒以下の間処理を繰り返すプログラムを書けばHIG4TOさんのやりたいことが実現できるのではないでしょうか。

今回はナノ秒のオーダーは必要ないと思われますので、単純に秒のみを比較します。
処理を繰り返すときは定期的にsleep()のような関数を呼び出さないとハングアップしてしまいますので注意です。

HIG4TOさんの環境が不明ですのでここではunistd.husleep()を使っていますが、Windowsなどの場合は代替となる関数(windows.hSleep()とか)をググってみてください。

時間情報の取得 clock_gettime() - 時間の扱い - 碧色工房

#include <time.h>
#include <unistd.h>

int main() {
    struct timespec start, current;
    time_t diff = 0;
    clock_gettime(CLOCK_MONOTONIC, &start);

    while (diff < 10) {
        usleep(0.5 * 1000000);  // 0.5秒待つ
        
        // その他いろいろやる

        clock_gettime(CLOCK_MONOTONIC, &current);
        diff = current.tv_sec - start.tv_sec;
    }
    
    return 0;
}
fj68fj68

Python スクレイピング件数が複数にまたがるときの条件分岐 | teratail


2ページ目のURLを見てみるとhttps://el.e-shops.jp/local/jb/6008/jn/6000523/cn/23109/2.htmlのように末尾に2.htmlが付いています。別の区の3ページ目も確認すると末尾が3.htmlでした。

ということはbase_urlhttps://el.e-shops.jp/local/jb/6008/jn/6000523/cn/23109/とすると、2ページ目はbase_url + '2.html'、3ページ目はbase_url + '3.html'……となっているわけです。

そして、最後のページの次のページ(例えばhttps://el.e-shops.jp/local/jb/6008/jn/6000523/cn/23109/3.html)を見てみると、.list-tel-shopという要素がないページが表示されます。

ここまでのことから、順番にURLを変えてアクセスしていって.list_tel_shopが取得できなくなったらその区はおわり、という判断の仕方ができます。

コードに落とし込むと、こんな感じでしょうか。

import requests
import re
from bs4 import BeautifulSoup

def get_shops_at_page(base_url, n):
    """ある区のn番目のページにあるすべてのlist_tel_shopを返す"""
    url = f"{base_url}{str(n)}.html" if n > 1 else base_url
    res = requests.get(url)
    soup = BeautifulSoup(res.text, 'html.parser')
    return soup.find_all('div', attrs={'class': 'list_tel_shop'})

def get_shops(base_url):
    """ある区のすべてのlist_tel_shopを返す
    返値は [{'name': '...', 'address': '...', 'tel': '...'}, {...}, ...]
    """
    shops = []
    n = 1
    # get_shops_at()が[]を返すまでどんどん次のページの情報を取得する
    while True:
        shop_els = get_shops_at_page(base_url, n)
        if not shop_els:
            break
        for shop_el in shop_els:
            # 以下、shop_el.find_all()でないのは「shop_el」つまり「.list_tel_shop」に
            # 「.shop_address」や「.shop_tel」といった要素が1つづつしか存在しないため
            shop = {}
            name = shop_el.find('a', href=re.compile("^/local/nsh/"))
            if name:
                shop['name'] = name.text
            address = shop_el.find('p', attrs={'class': 'shop_address'})
            if address:
                shop['address'] = address.text
            tel = shop_el.find('p', attrs={'class':'shop_tel'})
            if tel:
                shop['tel'] = tel.text
            shops.append(shop)
        n += 1
    return shops

# 複数の区の情報を得るなら以下のように使う

def flatten(xs):
    return list(itertools.chain.from_iterable(xs))

urls = [
    'https://el.e-shops.jp/local/jb/6008/jn/6000523/cn/23109/',
]

# [ [{...}, ...], [{...}, ...], ... ]になるのでflattenして[{...}, {...}, ...]に
shops = flatten([get_shops(url) for url in urls])

get_shops()ではshopごとに{'name': '...', 'address': '...', 'tel': '...'}という辞書を作ってそのリストを返すようにしています。

name/address/telそれぞれのリストがほしければ以下のようにしましょう。

names   = [shop['name'] for shop in shops]
address = [shop['address'] for shop in shops]
tels    = [shop['tel'] for shop in shops]

これらを一列づつ追加してもいいですが、一気にpd.Dataframeにした方がいい気がします。

import pandas as pd

# [[shopの社名, shopの住所, shopのTEL], [...], ...]に変換
data = [[shop['name'], shop['address'], shop['tel']] for shop in shops]
df = pd.DataFrame(data, columns=['社名', '住所', 'TEL'])
fj68fj68

map関数の使い方について | teratail


xs.map(f)は配列xsのすべての要素に対して関数fを適用した結果の配列を返します。
言い換えれば、xsのすべての要素に対してf(xs[0]), f(xs[1]), ...と適用した結果の配列を返します。
具体的には、以下のように使います。

const xs = [0, 1, 2]
const ys = xs.map(x => x + 1)   // xsのすべての要素に1を足す
// ys は [1, 2, 3]

一方、xs.slice(n)は配列xsn番目より後の要素を返します。

const xs = [0, 1, 2, 3, 4]
const ys = xs.slice(2)   // xsの2番目より後の要素=3番目から最後まで
// ys は [2, 3, 4]

したがって、list.slice(0).children.maplist.slice(0)が配列(中身は空[])なのでchildrenundefinedになってしまい、エラーが出たのではないかと思います。
list[0].children.mapでいいのではないでしょうか。


以上の話を踏まえた上で、実現したいことはlistの要素を2つづつ<div class="grid-inner">〜</div>に入れるということでよろしいでしょうか。であれば、まずlistの要素を2つづつ取り出してlist_by_2という配列にし、その配列をArray.prototype.mapで操作していきましょう。

「配列の要素を2つづつ取り出して配列にする」ために「配列をn個づつに分割する」関数を定義します。
JSで配列をn個ずつに分割 - Qiitaのコードを使っています。

const split = (array, n) => array.reduce((a, c, i) => i % n == 0 ? [...a, [c]] : [...a.slice(0, -1), [...a[a.length - 1], c]], [])

これをlistに適用すると、[ [{...}, {...}], [{...}, {...}], ... ]listの要素が2つづつ配列に入った配列になります。そしてlist_by_2.map(items => ...)items[{...}, {...}]となりますから、再びitems.map(item => ...)とすることでitem{_id: ..., children: ..., name: ...}となります。

そんな感じで書いていくと、以下のようになると思います。

// from: https://qiita.com/guttyar2213/items/46230300c5100a06198c
const split = (array, n) => array.reduce((a, c, i) => i % n == 0 ? [...a, [c]] : [...a.slice(0, -1), [...a[a.length - 1], c]], [])

const Grid = (props) => {
  // list_by_2: [{...}, {...}, ...] -> [ [{...}, {...}], [{...}, {...}], ... ]
  const list_by_2 = split(list, 2)
  return (
    <div className="grid">
    {list_by_2.map(items => (  // ​itemsは[{...}, {...}]
      <div className="grid_inner">
​        items.map(item => (
         ​ <div className="title"><a href={item._id}>{item.name}</a></div><ul className="footer-category-links">{item.children.map(({_id, name}) => (   // child => ...の代わりに ({_id, name}) => ...と分割代入しています<li key={_id}><a href={_id}>{name}</a></li>)}</ul>
        )
      </div>)}</div>)
}
fj68fj68

discord.pyにてある特定のserverのみコマンドを使えるようにしたい | teratail


message.channelTextChannelのインスタンスのとき(DMChannelGroupChannel以外のサーバに属しているメッセージのとき)、TextChannel.guildにサーバ情報がはいっているのでそれを使えば判定できます。

Message - API Reference

GUILD_ID = 'サーバのID'

@client.event
async def on_message(message):
    if not isinstance(message.channel, discord.TextChannel) or message.channel.guild.id != GUILD_ID:
        # 特定のサーバでなければなにもしない
        return
    # ... なにかする ...
fj68fj68

特定の時刻になったらボイスチャットから切断する | teratail


require()はできるだけファイル冒頭でする

細かいことですが、そのファイルがどんな外部モジュールに依存しているかをファイル冒頭にまとめておくと見やすいので、require()はできるだけファイルの冒頭に書きましょう。

varconstにしています。

const cron = require('node-cron')

/* ... なんやかんやあって ... */

client.on('ready', () => {
    /* ... いろいろする ... */
})

client.guilds.fetch(guildID)ではなくclient.guilds.cache.get(guildID)

client.guilds.fetch()は引数にサーバID(Snowflake)ではなくサーバオブジェクト(GuildResolvable)を渡さなくてはならないので、代わりにclient.guilds.cache.get(guildID)を使います。

cron.schedule('00 17 * * *', async () => {
        const guildID = 'ギルドID'

        const guild = client.guilds.cache.get(guildID);
        /* ...guildを使ってなにかする... */

guild.channels.cache.filter()Collectionを返す

Array.prototype.filter()と同じような関数で、返値はChannelではなくCollectionです。

そのため、各チャンネルのmembersプロパティを取得するにはCollection.each()しましょう。

const vchannels = guild.channels.cache.filter(channel => channel.type === 'voice')

vchannels.each(vchannel =>
  vchannel.members.each(/* ... */)
)

ユーザをVoiceChannelから退出させる方法

いくつか方法があり、その中でもバージョンによって動くものと動かないものがあるようです。

member.voice.setChannel(null)member.setVoiceChannel(null)はメンバーのチャンネル情報をnullに設定することにより、ボイスチャンネルから退出させるというものです。

一方、member.voice.disconnect()member.voice.kick()は文字通りメンバーをボイスチャンネルから退出させるために用意された関数です。
バージョンによってdisconnect()が使える・使えない分かれるようですが、どのバージョンから使えるのかは残念ながらわかりません。kick()は公式ドキュメントから見つけることすらできませんでしたが、ユーザ発の情報では割とありましたので、昔からある方法なのかもしれません(この辺は伝聞になってしまいますが申し訳ない)。

【追記】
hinanonさんによると「await member.voice.kick().catch(console.error)にしたら動きました」とのことです。
以下のコードもその情報に合わせて修正しました。

member.voice.disconnect('理由')member.voice.kick()Promiseを返す 非同期関数 なので、awaitで処理が終わるまで以降のコードの実行を中断します。
awaitを使うにはそのコードが含まれる関数をasyncにしなければいけないので、そこも修正します。

また、細かいことですが、if文周りでバグが入りそうなコードになっている(おそらくmember == nullのときでもconsole.log(member.id)が実行される)ので{...}で範囲を明確にしました。
ifwhileなどは例え1行だとしてもif (...) {...}にしておくと意図しない動作を防げます。

vchannel.membersCollectionなので、forEach()ではなくeach()を使っています。

vchannel.members.each(async member => {
  if (member) {
    // disconnect()を使う方法
    await member.voice.disconnect(`2時になったのでボイスチャットからキックしました(*'▽')`).catch(console.error)
    
    // kick()を使う方法
    await member.voice.kick().catch(console.error)
    
    console.log(member.id)
  }
})

channel.send()Promiseを返す

Promiseを返す関数は基本的にawaitして.catch()でエラー処理するようにしましょう。

なお、await member.voice.disconnect()するとdisconnect()の処理が終わるまでそれ以降のコードの実行を中断するので、その後にメッセージを送る場合もsetTimeout()disconnect()の処理が終わるまで待つ必要はありません。

await member.voice.disconnect(`2時になったのでボイスチャットからキックしました(*'▽')`).catch(console.error)

/* 処理待ちは必要ない */ 
await channel.send(`2時になったのでボイスチャットからキックしました(*'▽')`).catch(console.error)

こんな感じでしょうか。
一応、guild, vchannels, channelnullundefined, []だった場合のエラー処理をしていませんのでご注意ください。
ご参考まで。

fj68fj68

連想配列の不要なデータを削除しソートする方法について | teratail


質問者さんのように2つの処理に分けてforeachする考え方で全く問題ないと思います。

ソートする方の関数がよくわからないことになっていますが……
foreachの中でmultisort()を呼び出すのではなく、foreachでソート用にpriceの値のみの配列$sort_keysを作った後にforeachの外で1回だけmultisort()を呼べばいいのではないでしょうか。

foreach ($data as $key => $value) {
    $sort_keys[$key] = $value['price'];
}
multisort($sort_keys, SORT_ASC, $data);

個人的に配列の操作は(よほど複雑でなければ)foreachよりarray_*()系の関数の方がわかりやすいかなと思っているので、こう書くかなと思いました。

// priceがsoldのものを除く
$data = array_filter($data, fn($x) => $x['price'] !== 'sold');
// priceで昇順に並び替え
array_multisort(array_column($data, 'price'), SORT_ASC, $data);
fj68fj68

画像挿入の条件分岐のコード修正をお願いします。 | teratail


本題に入る前に、細かいことで恐縮ですが、質問する時はコードをコードブロックで囲っていただければ幸いです。
詳しくは以下をご覧ください。

質問する際にMarkdownは必ず使って欲しい - Qiita

Saienn877さんのコードをみる限り、JavaScriptやHTMLの基礎がまだ十分身についていないようだと感じました。
そのため、できるだけ丁寧に説明しようとした結果、すごく長くなってしまいました。
大変恐縮ですが、ご参考になれば幸いです。


対応していない</fieldset>

</fieldset>に対応する<fieldset>がなかったので補うか、削除しましょう。
今回は特になにかに使っているわけではないようなので、シンプルに削除してしまってよいと思います。

<input type="text"><select>〜</select>

ご質問のコードを読むと、ユーザからの入力はあるないしか想定していないようです。
このように「特定の値から一つを選んでもらう」ためのHTML要素は<input type="radio"><select>があります。
今回の場合は<select>がよいのではないでしょうか。

また、<input type="text">id属性もshowMessageだとよくわからない上、コード中で使っていないのでとりあえず削除しました。

<form name="js"><br>
  <select name="yourarea" autocomplete="on">
    <option value="ある">ある</value>
    <option value="ない">ない</value>
  </select>
</form>

フォームの値の取得

JavaScriptでフォームの値を取得する方法はいくつかありますが、今回はname属性を指定しているのでそれを使いましょう。

また、JavaScriptでは再代入できない変数(≒中身を書き換えない変数)を宣言するのにconstを使います。
というか、できるだけconstを使い、「const宣言した変数に代入しようとしてるよ」という旨のエラーが出たらletに書き換える、くらいにした方がよいでしょう。

iという変数名では何を表しているのか不明なので、yourareaという名前に変えておきます。

const yourarea = document.forms.js.elements.yourarea.value;

見やすい条件分岐にする

条件分岐はswitchでもできますが、今回はあるないと「未選択」だけなので、if〜elseで十分です。

JavaScriptでは文字列を"〜"'〜'で囲みますので注意しましょう。
また「ある文字列と別の文字列が等しい」ということを表すには===を使います。
ユーザが<select>の値を未選択のときはyourareaの値は空文字列(""'')となりますので、「yourareaの値を!を使ってfalseに変換できるか」をもとに判定します。

if (!yourarea) {
  /* 未選択の時の処理 */
} else if (yourarea === "ある") {
  /* 「ある」の時の処理 */
} else {
  /* それ以外、つまり「ない」の時の処理 */
}

もしどうしてもswitchで書きたいのであれば以下のようにすればよいでしょう。

switch (yourarea) {
  case "ある":
    /* 「ある」の時の処理 */
    break;
  case "ない":
    /* 「ない」の時の処理 */
    break;
  default:
    /* それ以外、つまり未選択の時の処理 */
    break;
}

switchの各caseについて

caseの中をみると、funcion loadImage(id) {〜}となっています。
しかし、function() {〜}というのは関数宣言でして、関数は宣言しただけでは実行されません。
関数を実行するには関数名(引数)と書きます。今回ならloadImage("<canvas>要素のID")ですね。

また、関数宣言は(基本的には)一度すれば十分ですから、tbox1()関数の外に定義しておきましょう。
そもそもfunction tbox1( {と文法エラーがありますので、そこも直します。

というわけで、ここまでのJavaScriptのコード部分をまとめるとこうなります。

function loadImage(id) {
  /* 画像を読み込む処理 */
}

function tbox1() {
  const yourarea = document.forms.js.elements.yourarea.value;

  if (!yourarea) {
    /* 未選択の時の処理 */
  } else if (yourarea === "ある") {
    /* 「ある」の時の処理 */
  } else {
    /* それ以外、つまり「ない」の時の処理 */
  }
}

JavaScriptで画像を表示するには

Saienn877さんはCanvas APIを使われていますが、ただ画像を読み込んで表示するだけにはちょっと大げさなように思います。
「Canvas APIで画像処理をしたい」などでなければ、予め<img>要素を用意していおいてそれを取得し、src属性に画像のURLを指定することで画像を読み込むようにすれば十分かと。

というわけでまずは<img>をHTMLに追加します。
検索ボタンの下に表示するようにしてみます。
単純にボタンの後に<img>を追加すると改行されず見づらいので、ボタンの後に改行(<br>)を追加し、その後に<img>を追加します。
あとでJavaScriptから探しやすいよう、id属性もつけておきます。

<input type="button" value="検索" onclick="tbox1()"><br>
<img id="result" alt="検索結果の画像">

では追加した<img>を探して画像を読み込む処理をloadImage()関数に書いていきます。
loadImage()関数を読むとあるないのそれぞれの場合の違いは画像のURLだけなので、引数から未使用だったidを削除し、代わりにurlを指定するようにしました。

function loadImage(url) {
  // <img>要素を探す
  const img = document.getElementById("result");
  if (img) {
    // <img>が見つかったら、src属性にURLを指定して画像を読み込む
    img.src = url;
  }
}

どうしてもCanvas APIを使いたい場合も同様に、HTMLに<canvas>を追加してloadImage()で探します。
画像は<canvas>とは別にメモリ上に読み込み、画像の読み込みが終わったらCanvasに描画します。
この処理はほとんど質問にあるコードと同じですね。

<input type="button" value="検索" onclick="tbox1()">
<canvas id="result"></canvas>

<script>
function loadImage(url) {
  // <canvas>を探す
  const canvas = document.getElementById("result");
  const context = canvas?.getContext('2d');  // .? はオプショナルチェーン演算子といいます
  if (canvas && context) {                   // canvasとcontextが取得できたら
    const image = new Image();               // 画像オブジェクトを用意
    image.src = url;                         // URLの画像を読み込む
    image.addEventListener("load", () => {   // () => {...} はアロー関数といいます
      // 読み込みが完了したらCanvasのサイズが画像のサイズと同じになるように設定して描画
      canvas.width = image.width;
      canvas.height = image.height;
      context.drawImage(image, 0, 0);
    })
  }
}

/* その他いろいろ */
</script>

各条件ごとの処理

あとはyourareaの値にあわせてloadImage()を呼び出すだけです。

まず、未選択の場合は「検索」ボタンが押されても何もしないようにします。
これを実現するのは簡単で、ただtbox1()関数の処理を終えればいいだけです。

if (!yourarea) {
  return;   // 未選択なら何もしない
} else if (yourarea === "ある") {
  /* 「ある」の時の処理 */
} else {
  /* それ以外、つまり「ない」の時の処理 */
}

「ある」と「ない」のときはそれぞれURLが異なる画像を読み込むので、loadImage()を呼び出します。
「ある」の時のURLが画像ではなくHTMLだったので、適宜変えてください。

if (!yourarea) {
  return;   // 未選択なら何もしない
} else if (yourarea === "ある") {
  loadImage("「ある」のときの画像のURL");
} else {
  loadImage("https://image.itmedia.co.jp/nl/articles/1701/21/l_miya_170121hagehair10.jpg");
}

以上、長くなってしまってすいませんでした。
コードをコピペしたり写経したり参考にしたりするときは「そのコードが何をしているのか」を(なんとなくでいいので)把握するようにすると、思い通りのプログラムを自分の力で書くことができるようになると思います。
わかりにくいところもあったかと思いますが、頑張ってみてください。

fj68fj68

関数とポインタについて | teratail


int型の変数に格納されている値を100に変更」する関数とのことですが、どちらの関数も引数の型が意図したものとは違うように思います。

hundred1(int a)は引数がint型なので値そのものがコピーして渡されますから、書き換えられたとしても関数を抜けるとその値は保存されないので意味がないでしょう。
以下のようなコードを書いて実行すると確認できます。

#include <stdio.h>

void hundred1(int i) {
    i = 100;    // 引数を書き換えてみるが……
    return;
}

int main() {
    int a = 50;
    
    printf("a = %d\n", a);
    hundred1(a);
    printf("a = %d\n", a);

    return 0;
}

hundred2(int** b)は逆にint型のポインタのポインタとなっているため、引数の中身(int型の値)にアクセスするには**bと2回 デリファレンス する必要があります。


ポインタについてまだ十分な理解ができていないのかなと愚推します。
その場合は以下を読んでいろいろとコードを書いて、しっかり理解しましょう。

【C言語】ポインタを初心者向けに分かりやすく解説 - だえうホームページ
「値渡し」と「参照渡し」の話 ポインタ渡しとは? - Qiita

#include <stdio.h>

void hundred(int* i) {
    *i = 100;  // ポインタが指し示す先の値を変更する
    return;
}

int main() {
    int a = 50;
    printf("a = %d\n", a);
    hundred(&a);     // 変数を書き換えられるようにポインタを渡す
    // hundred1(a);  // これだと値をコピーして渡しているので書き換えられない
    printf("a = %d\n", a);
    return 0;
}

コメントを参考に回答を改善しました。
みなさんありがとうございます。

fj68fj68

オブジェクトを見やすく変換したい | teratail

他の回答者の回答も参考になる。


こういったデータ変換系の話は、一歩々々に分けて考えるとやりやすいです。

というわけで、まずは{ "node": { "description": ..., ... } }{ "description": ..., ... }に変換するコードを考えます。

const edge = { "node": { "description": ..., ... } };

const node = edge["node"];

次は{ "edges": [...] }[...]に変換するコードです。

const products = { "edges": [...] };

const edges = products["edges"];

上記のことから、{ "products": { "edges": [{ "node": { "description": ... } }, ...] } }{ "products": [{ "description": ... }, ...]に変換するのは以下のように書けます。

const data = {
  "products": {
    "edges": [{
      "node": {
        "description": "Sleek and black",
        "featuredImage": {
          "id": "gid://shopify/ProductImage/15464783282345",
          "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb20.jpg?v=1602116082"
        },
        "handle": "skirt",
        // ...
      },
    }],
  },
};

const result = {
  "products": data["products"]["edges"].map(edge => edge["node"])
};

"images"の中身も入れ子にはなっていますが、同様に処理できます。
一点、{ ...node, "image": 〜 }としてnode["image"]だけを書き換えていることに注意です。
で、これらを踏まえ、こんな感じでどうでしょうか。

const data = {
  "products": {
    "edges": [{
      "node": {
        "description": "Sleek and black",
        "featuredImage": {
          "id": "gid://shopify/ProductImage/15464783282345",
          "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb20.jpg?v=1602116082"
        },
        "handle": "skirt",
        "images": {
          "edges": [{
            "node": {
              "id": "gid://shopify/ProductImage/15464783282345",
              "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb20.jpg?v=1602116082"
            },
          }],
        },
        // ...
      },
    }],
  },
};

const result = {
  "products": data["products"]["edges"].map(
    edge => edge["node"]
  ).map(    // ここまでで{ "products": [{ "description": ... }, ...] }になっている
    node => ({ 
      ...node,
      "images": node["images"]["edges"].map(
        edge => edge["node"]
      )
    })
  ),
}

console.log(JSON.stringify(result, null, 2));

/* result
{
  "products": [{
    "description": "Sleek and black",
    "featuredImage": {
      "id": "gid://shopify/ProductImage/15464783282345",
      "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb20.jpg?v=1602116082",
    },
    "handle": "skirt",
    "images": [{
      "id": "gid://shopify/ProductImage/15464783282345",
      "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb20.jpg?v=1602116082",
    }],
  }],
}
 */
fj68fj68

遅刻3回で欠席1回分としてカウントするにはどうしたらいいか? | teratail


求めたい欠席欠席日数 + 遅刻を3回毎に1でしたね。

遅刻を3回毎に1というのはつまり、遅刻した日数を3で割ったときの商です。
例えば「遅刻が4回なら4÷3=1あまり1なので欠席1」、「遅刻が10回なら10÷3=3あまり1なので欠席3」のように、3で割ったときの商で求められます。
そして、Excelには商を求めるためのQUOTIENT関数があります。

以上のことから、欠席日数遅刻日数がそれぞれD12/D13に入っているとすると、欠席=SUM(D12,QUOTIENT(D13,3))となるのではないでしょうか。

いま手元にExcelがないのでコードの検証はしていませんが(申し訳ない)、「こんな風に考えるといいのではないか」という考え方の部分だけでも参考になれば幸いです。

fj68fj68

cssについて教えてください。 | teratail


text-align: right;というのは「中身を行ボックスの右辺に寄せる」ことを表します。
行ボックスというのはbibiyellowさんが仰るところの「aquaライン」のことです。

left/rightという字面にとらわれると「右辺」というのは「画面における右側」と思いがちですが、実はそうではありません。あくまで「行ボックス」の「右辺」です。

CSSには「フロー」と「書字方向」という概念があります。簡単に言えば、「要素をどの方向に詰めていくか」「文字などをどの方向から書くか」を決めるためのものです。text-alignなどのプロパティはフローや書字方向に基づいて見た目の挙動が変わります。

普段はフロー方向が水平で書字方向が左書きなので「行ボックスの右辺」は「画面における右側」と一致してします。しかし今回の場合、縦書きで右書きになっているため、結果的に「行ボックスの右辺」が「画面における下側」の方向になっています。

もっとシンプルに「要素が時計回りに90度回転している」と考えてみるとわかりやすいかもしれません。


なお、縦書きにしているときはtext-alignの値をleft/rightではなくstart/endにした方が混乱しにくく、おすすめです。

fj68fj68

ネストされた連想配列の更新について | teratail


ある配列の特定の要素を更新する処理はArray.prototype.map()を使って以下のように書きます。

const update = (arr, index, value) =>
  // mapに渡す関数で、i番目の要素ならvalue、それ以外はオリジナルを返すことで、配列を更新する
  arr.map((v, i) => i === index ? value : v);

あるオブジェクトの特定のプロパティの値を更新する処理はスプレッド構文を使って以下のように書けます。

const updateId = (obj, newId) =>
  // スプレッド構文でオブジェクトの中身を展開し、キーが"id"のプロパティの値はnewIdにすることで更新する
  ({ ...obj, id: newId });

キー名も引数で指定したいときはこうです。

const update = (obj, key, value) =>
  // スプレッド構文でオブジェクトの中身を展開し、キーがkeyのプロパティの値はvalueにすることで更新する
  ({ ...obj, [key]: value });

よって、配列の中のi番目のオブジェクトのcheckedプロパティを更新する処理はこう書きます。

const update = (arr, index, value = true) =>
  arr.map((item, i) => ({
    ...item,
    checked: (i === index) ? value : item.checked,
  }));

const data = [{
  id: "a",
  checked: false,
}, {
  id: "b",
  checked: false,
}];

const b_checked = update(data, 1);

/*
b_checked = [{
  id: "a",
  checked: false,
}, {
  id: "b",
  checked: true,  // 2番目のオブジェクトのcheckedプロパティが更新される
}];
 */

というわけで、これらを踏まえて考えてみると、以下のようになるのではないでしょうか。

parent_idchild_idを指定して更新するパターンと、配列のインデックスを指定して更新するパターンを作ってみました。

// parent_idとchild_idを指定して更新
const updateCheckById = (data, parentId, childId, value = true) =>
  data.map(parent => ({
    ...parent,
    state: parent.state.map(child => ({
      ...child,
      checked: (parent.parent_id === parentId && child.child_id === childId) ? value : child.checked,
    })),
  }));
// インデックスを指定して更新
const updateCheckByIndex = (data, parentIndex, childIndex, value = true) =>
  data.map((parent, parent_index) => ({
    ...parent,
    state: parent.state.map((child, child_index) => ({
      ...child,
      checked: (parent_index === parentIndex && child_index === childIndex) ? value : child.checked,
    })),
  }));

以上、お役に立てれば幸いです。